React/Redux - New props - componentDidUpdate not called - reactjs

I'm working on a new React/Redux code base. I have a component connected to Redux through a container component. Basically, there is a piece of data within the store that has an id. That id corresponds to a conversation that needs to be loaded. When that number changes, we have a new prop. The component re-renders. And the componentDidUpdate method SHOULD be called... except it is not.
Again:
New data comes in (I have confirmed this with a console.log)
Component re-renders (I have confirmed this with a console.log)
...but componentDidUpdate is not called. I need it to be called.
I looked in Redux state, and the state changes. But there is no difference in Redux tools. I can visually see the data changing in state, but redux tools detects no "difference." AKA, even though the raw data is changing, the system does not detect it.
Could this happen if a reducer returns a mutated, original copy of state rather than a new copy?

Related

Reducer Props getting changed in the component

In my React app, I have a redux reducer which sends a List as props to my component.
I copy the prop to local state, and show as drop down. User changes the Dropdown so my local state changes.
On click of cancel , I am calling redux Toastr which triggers a method to reset my state with the original props.list. But for some reason the props.list also changed similar to my state change. With my knowledge i thought props passed to the componeent will not be changed until again i call action creator.
Anyone faced similar issue? or i am doing something wrong
Sorry for not posting the code, which I will prepare a demo if needed. Thanks!
What you are doing is an anti-pattern as you are breaking react's rule of single source of truth. You can't hold state internally in a component that is tied up with your redux state and expect it work smoothly. A similar issue of breaking the single source of truth arise when using solely React without Redux and when you try to pass props as state. In this case there is a new lifecycle hook static getDerivedStateFromProps but even this hook is advised to be used sparsely you can read about it here. So if your intent is to reset state back to it's original value, you can either:
Use static getDerivedStateFromProps (which is reserved mostly for UI)
Use a key prop which will reset you back to your initial state
Use a memoization helper such as memoize-one

Components update in Redux

So in plain react, setState triggers the render method. Now, about Redux, let's say I fire an action, the state returned from the reducer(s) is totally new, so it sounds like every component should get updated, though I know it's not true because when I debug my app I can see it, plus it sounds like awful performance. So my question is, does redux look in each component what state slice it needs? in mapStateToProps? and generally how does Redux decide when to call the render method?
I know Redux has optimizations in it... thanks...
A Redux store offers a subscribe() method. When you use connect(), it generates wrapper components that automatically subscribe to the store when they are created. Each individual connected component is a separate subscriber.
When an action is dispatched, the store runs all the subscription callbacks. The wrapper components then call store.getState(). As a first check, if the root state object is === identical to the previous one, the component will stop there. (This is one reason why direct mutation of state in a reducer is bad.)
The next step is to call the provided mapState function and pass in the current state object. The wrapper component then compares the contents of the object returned from mapState against the contents of the object returned last time, using a shallow equality comparison check. If any of the contents have changed based on that shallow check, then the component knows it needs to re-render the "real" component with the new data. (Again, the "shallow" check is another reason why mutation is bad.)

React + Redux: Scrolling a DOM element after state change

New to Redux here, really just looking for a "best practice" answer.
I am building a chat application using React + Redux. My app looks something like this:
3 stateless components for my app container, message list, and input bar
Actions for adding user messages/responses
A reducer that takes in these actions and returns a messages array
Chat middleware which handles a emitting a socket message when then ADD_MESSAGE action is dispatched
So far so good. Everything is working well, however I'm unsure of how/where in this sequence I should be making DOM manipulations. Specifically, I would like to scroll to the bottom of my message-list container whenever my messages state changes.
All I need to fire is something like: messagesListElement.scrollTop = messagesListElement.scrollHeight;, but not sure where the appropriate place to do this is.
You mentioned that all the three components are stateless which means the messages are maintained in redux store which means they are passed as props to the child components. Basically there are five life cycle methods which could get triggered after/before the component gets updated.
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
render()
Now since you want to scroll down after a new message is pushed to the messages state, the best place to do this would be componentDidUpdate()
Why not componentWillReceiveProps - This is the function which will get executed just before a new message is about to be passed in the new props of the component. This is the best place to update your component's state against the new props but since your component is stateless, this is not the right place for scrolling. This could be helpful
Hope it helps :)

All component gets rendered even if we required to render only one, in react-redux

I'm not sure it is default behaviour or redux or something else but i found that on dispatching an action, this action traverse through all reducers(that's ok) but it also invoke the connect listener of every reducer that further resulting rendering of its component. This means on every dispatch, all component inside app state tree get rendered. Is this intentionally done by redux or i've done something wronge.
Help me out to clarify this things.
In Redux , your state is global and handled by the redux, whenever you dispatch an action , you are just setting the global state. Your container comonents will receive the new state and reducer would work on them but your components wont be rerendered since previous state and next state would be same.
Only those components would be rendered whose mapStatetoProps result in a different result
This behavior is totally fine. See the React Docs for their virtual DOM concept:
React makes use of a virtual DOM, which is a descriptor of a DOM subtree rendered in the browser. This parallel representation allows React to avoid creating DOM nodes and accessing existing ones, which is slower than operations on JavaScript objects. When a component's props or state change, React decides whether an actual DOM update is necessary by constructing a new virtual DOM and comparing it to the old one. Only in the case they are not equal, will React reconcile the DOM, applying as few mutations as possible.
So you don't have to worry that every component will get re-rendered every time you dispatch an action.

ReactJS: Why is passing the component initial state a prop an anti-pattern?

I've created a small ReactJS dashboard with the help of SocketIO for live updates. Even though I have the dashboard updating, it bugs me that I'm not quite sure if I did it correctly.
What bugs me the most is the Props in getInitialState as anti-pattern post. I've created a dashboard that gets live updates from a server, requiring no user interaction beyond loading the page. From what I've read, this.state should contain things that will determine whether the component should be re-rendered, and this.props.... I don't know yet.
However, when you initially call React.render(<MyComponent />, ...), you can only pass props. In my case, I get all data from the server, so the initial props just end up in this.state anyway. So all of my components have something like this:
getInitialState: function() {
return {
progress: this.props.progress,
latest_update: this.props.latest_update,
nearest_center: this.props.nearest_center
}
}
Which, unless I've misinterpreted the aforementioned blog post, is an anti-pattern. But I see no other way of injecting the state into the Component, and I don't understand why it's an anti-pattern unless I relabel all of my props to prepend initial on them. If anything, I feel like that's an anti-pattern because now I have to keep track of more variables than I did before (those prepended with initial and those without).
Disclaimer: When I answered this question I was learning / trying to
implement vanilla Flux and I was a bit skeptic about it. Later on I
migrated everything to Redux. So, an advice: Just go with Redux or
MobX. Chances are you won't even need the answer to this question
anymore (except for the science).
Passing the intial state to a component as a prop is an anti-pattern because the getInitialState method is only called the first time the component renders. Meaning that, if you re-render that component passing a different value as a prop, the component will not react accordingly, because the component will keep the state from the first time it was rendered. It's very error prone.
And here is what you should do:
Try to make your components as stateless as possible. Stateless components are easier to test because they render an output based on an input. Simple like that.
But hey.. my components data change.. I can't make them stateless
Yes you can, for most of them. In order to do that, select an outer component to be the state holder. Using your example, you could create a Dashboard component that contains the data, and a Widget component that is completely stateless. The Dashboard is responsible for getting all the data and then rendering multiple Widgets that receive everything they need through props.
But my widgets have some state.. the user can configure them. How do I make them stateless?
Your Widget can expose events that, when handled, cause the state contained in Dashboard to change, causing every Widget to be rerendered. You create "events" in your Widget by having props that receive a function.
Ok, so now, Dashboard keeps the state, but how do I pass the initial state to it?
You have two options. The most recomended one, is that you make an Ajax call in the Dashboard getInitialState method to get the initial state from the server. You can also use Flux, which is a more sophisticated way for managing data. Flux is more of a pattern, rather than an implementation. You can use pure Flux with the Facebook's implementation of the Dispatcher, but you can use third-party implementations like Redux, Alt or Fluxxor.
Alternatively, you can pass this initial state as a prop to the Dashboard, explicitly declaring that this is just the initial state.. like initialData, for instance. If you choose this path, though, you can't pass a different initial state to it aftwards, because it will "remember" the state after the first render.
OBS
You are not quite right in your definitions.
State is used to store mutable data, that is, data that is going to change during the component life-cycle. Changes in the state should be made through the setState method and will cause the component to re-render.
Props are used to pass in imutable data to the components. They should not change during the component life-cycle. Components that only use props are stateless.
This is a relevant source on the "how to pass the initial state to components".

Resources