React Hook component doesn't update on imported array change - javascript

I have some mocked data in usersList.js file.
Also I have created a service to add users to this array.
But component, which is responsible for rendering this data, is rendering only once. Any changes occured in usersList doesnt affect on re-render.
I try to use useEffect, but it didn't help.
Only force update can re-render it, but I am not satisfied of this solution.
userList.js
const usersList = [{...}]
export default usersList

Any changes occured in usersList doesnt affect on re-render.
That's because if you're using usersList as React state and modifying usersList, you're breaking one of the fundamental React rules. You cannot directly modify state arrays/objects.
Instead, you replace the array/object in the state, via the setter function that useState returns (or in a class component, via setState).
If this is all happening outside the component, you need to have something notify the component that things have changed, so the component can update its state. That might be using context or something else, but fundamentally the component needs to know that it needs to update its state.

Related

Redux simulated component update

What is the most efficient way in (functional) React to update a component when a variable changes value?
A piece of code somewhere in the program (over which I have no control) changes a variable e.g. an array in a "Redux" compatible way (i.e. a new reference is returned).
I would like to simulate Redux's useSelector without having to have to use Redux.
Updating the component means you need useState, Not sure what exatcly you are looking for, But if you want to update the component without much Props drilling, then i will suggest you to look into the Context-API on react.
This way you can have control like redux, without redux.
https://reactjs.org/docs/context.html

Debug react component rerender

I'm trying to debug bug that is reproduced very rarely (once per several dozens of trys).
I'm inside of render call and want to find out as much information as possible from there:
What caused rerender: forceUpdate, setState or props changed?
If it was a props change, which component initiated chain of rerenders: I mean not the fact of parent render, but the top component from parents chain that has used setState or forceUpdate and so caused rerender of itself and the whole tree bellow (including the component I'm currently in).
It's guaranteed that all components are class components (not functional) and I'm using react 16.4.2 including deprecated lifecycle methods (if it is important). There are some usages of context too.
How can I make it? Note, I'm asking about debug techniques, not about fixing my concrete bug.
If your component is a pure component - extends React.PureComponent { ... }, you don't really have to care about the whole chain of re-renders, since it will re-render only if props have changed (from the chain or from the redux store).
It will not re-render if parent state changed or if parent basically has re-rendered.
However, it will still re-render - as I mentioned above - if props have changed or state inside that component was updated or forceUpdate function was called.
If you are not calling forceUpdate inside your component or you are not updating the state, the issue may be related with the props.
You could use e.g. componentDidUpdate and simply compare the prevProps with this.props and check which one of the props has changed.
Nonetheless, you can also check https://www.npmjs.com/package/#welldone-software/why-did-you-render package, it might be helpful for you.

Redux: How do partial re-renderings work?

This question is about internals for partial re-renderings with React-Redux.
To explain what I mean, I will first introduce a very crude technique for managing state without any state management libary.
The technique uses a a huge "AppState"-object that is owned by the top-level App-component.
Suppose that this AppState holds not only state-properties, but also several callbacks that mutate those state-properties.
Furthermore, suppose that we use props to pass down this AppState throughout the entire component hierarchy.
Thanks to the ES6-spread syntax, passing a huge number of props can be done without a lot of boilerplate code.
In the top-level App-component, it will look like this:
<ChildComponent {...this.state} />
In all other components, it will look like this:
<GrandChildComponent {...this.props} />
It is important to note that the ES6-spread syntax does not actually pass the AppState-object. Instead, it extracts all the AppState-properties and passes them as separate props.
Now we should distinguish between top-level properties and nested child-properties of the AppState:
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (unless I use things like pure components).
However, if I change a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This leads to my final questions:
What is the render-performance of this crude approach in comparison to Redux?
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (because everything depends on the AppState).
If you mutate and use pure components then nothing will render, you change state by creating a new state object.
However, if I mutate a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This is only true if you mutate and components are pure.
What is the render-performance of this crude approach in comparison to Redux?
Prop drilling will re render the entire tree but branches that use state that didn't change won't re render if they are pure. Prop drilling is bad for maintenance because if you need to refactor grand child state logic you may need to refactor the whole tree or branch. But from a performance point it would not take a big hit provided that you use pure components and are careful when passing callbacks and not re creating them on every render (see useCallback).
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
React-redux useSelector or connect mapStateToProps are always called every time dispatch changed state and before rendering.
If the result is different than last result then react-redux will trigger render of the component. If the component gets props then a render could also be triggered because props change and mapstate/selector will be executed.
A connected component will observe state and render when the result of mapState or selector has changed. An example app with logs showing what react-redux will execute can be found here
For state management, you don't necessarily have to use Redux, if your use cases are small, maybe React Hook would be perfect for you.
For React rerendering matter, what I know is there are several strategies (useMemo, PureComponents) provided by React for managing and improve the performance. It really depends on how you manage your components.
One example is using PureComponent, even if you have a large state in your top-level app.js, if you manage the child components properly, they will not re-render if their receiving props haven't changed.

Why is redux better than a simple object?

I am learning Redux. As I understand, Redux in React helps us to manage state of React app. But why can't I just use empty object to hold all necessary state changes?
For example, I have root component with two subcomponents.
<App>
<Label/>
<Button/>
</App>
Inside Label I have state {numb: 1} and one function, that increase numb
increase() {
setState(prevState => {
return {numb: prevState.numb + 1}
});
}
On top of this component I import Store.js file, that exports empty object, that I use to store all my change state functions.
import Store from './Store'
And in the constructor of Label, I just assign function from that component
Store.plusOne = this.increase
That helps me to import Store file inside Button component and use increase function to increase Label's numb property.
<button onClick={Store.increase}>Plus One to Label's numb</button>
So what is the point to use Redux, if I can store any state change function in a separate object?
I had the same feeling when I started with Redux a few years ago. "Man, this seems overly complicated". But then I realised while not using redux that I was doing the same things but less efficient and more error prone when doing things "manually".
Redux comes with a few powerful helper functions. The first one is connect which helps you to get those state properties into your components. You can literally connect your components to your state. You don't have to worry about anything else, change the state in a single place and watch the changes flow through your application.
Because you "plop" (yes, a technical term...cough) all the properties you need for that component from your state onto the props of your component you automatically get that the component refreshes when your state changes. Even while using pure functions or a PureComponent which might be very good for performance.
You can see it like this. If you want React + Redux to automatically reflow your application: use Redux. If you manually want to update a object and manually force your application to reflow, use a custom state object.
That being said, I think redux makes sense in bigger applications where multiple components depend on the same state. If you just have a single piece of data rendered in a single component or a demo app with a simple button click you might as well keep it simple with a small object.

How can you create a functional component that updates on Redux store change?

For my application, I want to create a component who's sole purpose is to update when there is a change to the Redux store.
I have achieved this with a componentDidMount() that checks if the component's state matches the store and sets the state if not.
My solution works, and is suitable enough for the situation, but it seems like a lot of code for a simple function.
How can one achieve the same outcome, a component that updates on Redux store change, using a functional component or a more simple stateful component?
Update: Thanks to the comments below, I have a new working the passes state information as props.
React components renders due to changes in props and state, therefore when you connect your component to Redux store
and supply mapStateToProps, when redux store update the mentioned props that you will return from that function, your component will re-render. You can detect changes via componentWillReciveProps life cycle method.

Categories