Reactjs - Lifting State Up VS Keeping a Local State

ReactJS - Lifting state up vs keeping a local state

As React docs state

Often, several components need to reflect the same changing data. We
recommend lifting the shared state up to their closest common
ancestor.

There should be a single “source of truth” for any data that changes
in a React application. Usually, the state is first added to the
component that needs it for rendering. Then, if other components also
need it, you can lift it up to their closest common ancestor. Instead
of trying to sync the state between different components, you should
rely on the top-down data flow.

Lifting state involves writing more “boilerplate” code than two-way
binding approaches, but as a benefit, it takes less work to find and
isolate bugs. Since any state “lives” in some component and that
component alone can change it, the surface area for bugs is greatly
reduced. Additionally, you can implement any custom logic to reject or
transform user input.

So essentially you need to lift those state up the tree that are being used up the Siblings component as well. So you first implementation where you store the selectedItems as a state in the RightContainer is completely justified and a good approach, since the parent doesn't need to know about and this data is being shared by the two child components of RightContainer and those two now have a single source of truth.

As per your question:

As feasible alternative I thought of adding a _selected property to
each item in state.right.data in MainContainer and pass the select
callback three levels down to SelectableList, handling all the
possible actions in MainContainer

I wouldn't agree that this is a better approach than the first one, since you MainContainer doesn't need to know the selectedItems or handler any of the updates. MainContainer isn't doing anything about those states and is just passing it down.

Consider to optimise on performance, you yourself talk about implementing a shouldComponentUpdate, but you can avoid that by creating your components by extending React.PureComponent which essentially implements the shouldComponentUpdate with a shallow comparison of state and props.

According to the docs:

If your React component’s render() function renders the same result
given the same props and state, you can use React.PureComponent for a
performance boost in some cases.

However if multiple deeply nested components are making use of the same data, it makes sense to make use of redux and store that data in the redux-state. In this way it is globally accessible to the entire App and can be shared between components that are not directly related.

For example consider the following case

const App = () => {
<Router>
<Route path="/" component={Home}/>
<Route path="/mypage" component={MyComp}/>
</Router>
}

Now here if both Home and MyComp want to access the same data. You could pass the data as props from App by calling them through render prop. However it would easily be done by connecting both of these components to Redux state using a connect function like

const mapStateToProps = (state) => {
return {
data: state.data
}
}

export connect(mapStateToProps)(Home);

and similarly for MyComp. Also its easy to configure actions for updating relevant informations

Also its particularly easy to configure Redux for your application and you would be able to store data related to the same things in the individual reducers. In this way you would be able to modularise your application data as well

Why do we need to keep state in parent component

In your example, if only the Accordion needs the state that's probably a better place (the example may not be correct). In general, a good rule to follow is keeping state as "specific" or as "narrow" as possible.

State only needs to be raised up in the tree (to its parent or an earlier ancestor) if other components that are children of those ancestors also need access.

However, if in your example, say the AccordionParent is rendering a different UI or doing something with isOpen then that's probably a good place for it (because it's generally a bad idea to expose a child's state to its parent).

What is the difference between state and props in React?

Props and state are related. The state of one component will often become the props of a child component. Props are passed to the child within the render method of the parent as the second argument to React.createElement() or, if you're using JSX, the more familiar tag attributes.

<MyChild name={this.state.childsName} />

The parent's state value of childsName becomes the child's this.props.name. From the child's perspective, the name prop is immutable. If it needs to be changed, the parent should just change its internal state:

this.setState({ childsName: 'New name' });

and React will propagate it to the child for you. A natural follow-on question is: what if the child needs to change its name prop? This is usually done through child events and parent callbacks. The child might expose an event called, for example, onNameChanged. The parent would then subscribe to the event by passing a callback handler.

<MyChild name={this.state.childsName} onNameChanged={this.handleName} />

The child would pass its requested new name as an argument to the event callback by calling, e.g., this.props.onNameChanged('New name'), and the parent would use the name in the event handler to update its state.

handleName: function(newName) {
this.setState({ childsName: newName });
}

State management in ReactJS

  1. For initial rendering and initialisation, one can passed down the props from parent component to Map Component.

    e.g. Initial zoom, geofence, default marker etc.

  2. Now from here onwards, if Map component have any changes, like new mark, geofence then you should manage local state at Map Component level and store the state internally with state. In case,APP need some info on this changed data then do state lifting.

  3. From APP,if again there is changes for Map component like resetting the Map Component, you should use componentWillReceiveProps to retrieve the props and do setState to render the Map Component again with these new reset data.Now,these new passed props going to save in Component state.



Related Topics



Leave a reply



Submit