I'm probably missing something very obvious and would like to clear myself.
Here's my understanding.
In a naive react component, we have states
& props
. Updating state
with setState
re-renders the entire component. props
are mostly read only and updating them doesn't make sense.
In a react component that subscribes to a redux store, via something like store.subscribe(render)
, it obviously re-renders for every time store is updated.
react-redux has a helper connect()
that injects part of the state tree (that is of interest to the component) and actionCreators as props
to the component, usually via something like
const TodoListComponent = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
But with the understanding that a setState
is essential for the TodoListComponent
to react to redux state tree change(re-render), I can't find any state
or setState
related code in the TodoList
component file. It reads something like this:
const TodoList = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
Can someone point me in the right direction as to what I am missing?
P.S I'm following the todo list example bundled with the redux package(https://github.com/reactjs/redux/tree/master/examples/todos/src/containers).
as i know only thing redux does ,on change of store's state is calling componentWillRecieveProps if your component was dependent to mutated state and then you should force your component to update its is like this
1-store State change-2-call(componentWillRecieveProps(()=>{3-component state change}))
The
connect
function generates a wrapper component that subscribes to the store. When an action is dispatched, the wrapper component's callback is notified. It then runs yourmapState
function, and shallow-compares the result object from this time vs the result object from last time (so if you were to rewrite a redux store field with its same value, it would not trigger a re-render). If the results are different, then it passes the results to your "real" component" as props.Dan Abramov wrote a great simplified version of
connect
at https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e that illustrates the basic idea, although it doesn't show any of the optimization work. I also have links to a number of articles on Redux performance that discuss some related ideas.update
React-Redux v6.0.0 made some major internal changes to how connected components receive their data from the store.
As part of that, I wrote a post that explains how the
connect
API and its internals work, and how they've changed over time:Idiomatic Redux: The History and Implementation of React-Redux
My answer is a little out of left field. It sheds light on a problem that led me to this post. In my case it seemed the app was Not re-rendering, even though it received new props.
React devs had an answer to this often asked question something to the tune that if the (store) was mutated, 99% of the time that's the reason react won't re-render. Yet nothing about the other 1%. Mutation was not the case here.
TLDR;
Edge Case: Once
state
updates, then the app does re-render !It turn out that if your app is using only
state
to display its elements,props
can update, butstate
won't, so no re-render.I had
state
that was dependent onprops
received from reduxstore
. The data I needed wasn't in the store yet, so I fetched it fromcomponentDidMount
, as is proper. I got the props back, when my reducer updated store, because my component is connected via mapStateToProps. But the page didn't render, and state was still full of empty strings.An example of this is say a user loaded an "edit post" page from a saved url. You have access to the
postId
from the url, but the info isn't instore
yet, so you fetch it. The items on your page are controlled components - so all the data you're displaying is instate
.Using redux, the data was fetched, store was updated, and the component is
connect
ed, but the app didn't reflect the changes. On closer look,props
were received, but app didn't update.state
didn't update.Well,
props
will update and propagate, butstate
won't. You need to specifically tellstate
to update.You can't do this in
render()
, andcomponentDidMount
already finished it's cycles.componentWillReceiveProps
is where you updatestate
properties that depend on a changedprop
value.Example Usage:
I must give a shout out to this article that enlightened me on the solution that dozens of other posts, blogs, and repos failed to mention. Anyone else who has had trouble finding an answer to this evidently obscure problem, Here it is:
ReactJs component lifecycle methods — A deep dive