Wednesday, September 29, 2021

React: useContext usage note

useContext provides an simple way to allow child components to directly access high level parent's data and methods without relaying the information through multiple levels. Context in react has two parts, one is context provider to wrap the root level parent component, and one is useContext to provide access for low level child components. The react provides a key function of createContext function, which returns a context object, the context object includes everything for getting the context provide, and specify the context's data member types, and accessing the context data members.
 
Regarding the context provider, contextProvider is a just regular react component, generated by createContext method. The only unique thing about it is, it has a property named as value, which must be set to an instance of the context type specified in createContext method. In the application's root component, any children wrapped directly or indirectly below contextProvider component can access the context data member using useContext hook.

useContext works in similar way as react component props, if context method provides set method, then children component can call this method to change values implemented in context provider component. However, if the context provider just sets the value as a regular js variable, then updating the js variable's value or object reference will not trigger rendering the provider component and its children components. Basically useContext just provides a special prop that can be accessed by all children components with useContext hook. Similar to other regular component properties, context.Provider just creates a snapshot of the current value that can be accessed by the children components.

So, unlike useState, context does not participate in the React change detection, there is no set method to update context value as useState does. A common practice is implementing the context's value using the useState hook in the provider component, so once state object is updated by the children component, it will trigger the rendering of the provider component, which will lead context.Provider component and its children component to update to the new state value.  

Note, in the root component that sets the context provider, there is no need to call useContext to get the context value, as it already has the context value to set as attribute of context provider. But in case useContext is called to get the context value, you will see the default value instead of the value set by myContext.Provider is returned. The reason is as when useContext(myContext) is called, which happens at the beginning of component function, myContext.Provider has not been executed, so it makes sense to return the default value by useContext(myContext) method. However, any children component wrapped within myContext.Provider will get the new value set by myContextProvider. 


React: useState Hook change detection

[myStateValue, setMyStateValue] = useState(myObject);

Component will render itself and its children components if its state has changed with useState hook.

If the state value is primary type, like string or number, then call setMyStateValue method will trigger the render if the value is not changed, then calling setMyStateValue will not cause re-rendering.

If the state value is an object, when calling setMyStateValue method, if both the object reference and object value have not been updated, then it will not cause an re-render. If the object's reference is not changed, but the object's property value is changed, then setMyStateValue will not cause a re-rendering due to the updated property values. The only case to lead to rendering is when the object reference is changed.  This means React only monitors and detects the reference change for useState object type, and ignore the object's property changes.

Calling setMyStateValue method will only cause re-rendering of the current component which defines the state object, which will also re-render all the children components. But it will not cause re-rendering of the current component's parent component. 

When calling setMyStateValue method, the new state parameter (myNewState) must contain the full value of the new state object, as it will replace the original state object. 

setMyStateValue(myNewState);

A better way to call setMyStateValue is passing in a function parameter, which takes a parameter of previous state, so that you can build the new state object based on the latest state object, and then return the new state object from the function parameter.

setMyStateValue( (previousState) => {

    return { ... previousState, propertyName:updatedPropertyValue};

}

React: Props are read-only

Props are read-only

Props passed in to component are read-only, they can never be changed within the received component. If a component tries to update the prop value passed to it , an exception will be thrown for the error "cannot assign to read-only property". Note, if the prop value is an object, then within the received component, it can change the object's property value without causing any exception, however, React will not detect the change of the prop's value, and will not render the component again for this change.

In the parent component which sets the props, if the prop is set from a regular js let variable, then after the child component is rendered, updating the let variable's value, i.e the props value passed to the child component, React will not detect the prop change and will not re-render the child component based on the updated prop value. The prop value passed to child component is just a snapshot when rendering the child component, and the parent component will not track any future change of a regular js variable. 

In short, React does not care about regular js variable change, and will not render again based on those changes.

In order to let React knows the change, useState hook should be used.



Sunday, September 26, 2021

Understand msal-react package used for react js project



In order to use Azure authentication for react project, two packages are needed to be installed in react project.

npm install @azure/msal-react @azure/msal-browser

Package @azure/msal-browser is the base package, which implements the basic function for msal authentication for javascript project, including server side node projects and client side html/js project.

Package @azure/msal-react is wrapper package around @azure/msal-browser, it provides react specific feature, like react hook and context, so react developers can easily integrate the msal features into the react projects.

To get familiar with msal-react package, developers should first read the document in 

https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-react#advanced-topics

https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-react

Developer may also want to refer to the document at the below link for msal-browser package, in order to understand certain inherited functions provided by msal-react package.

https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-browser