I've read this thread. What is the difference between state and props in React?
It says that props are different from states and ideally props should not be change in its component and only should be changed by its parent component.
However, mapStateToProps function in react-redux maps states in Redux to props of a React components, which is basically changing props of a React component when Redux state is changed by an Redux action.
It does not make sense to me. It seems that it should have been mapStateToStates instead and maps Redux states to states of a React component.
Am I missing something?
It says that props are different from states and ideally props should
not be change in its component and only should be changed by its
parent component.
State here refers to the internal state of the component, which the component can change internally via .setState().
However, mapStateToProps function in react-redux maps states in Redux
to props of a React components, which is basically changing props of a
React component when Redux state is changed by an Redux action.
The state here refers to the redux store, an external state. react-redux's connect method creates a HOC - higher order component (a component which is aware of the store's state changes). The HOC wraps the dumb react component, which is not aware of the store. Using mapStateToProps the HOC maps the data from the external state, and inject it to the react component via the props.
State in redux store -> mapStateToProps in HOC -> props passed to the dumb component
So the HOC is the parent, and the dumb component is the child. The parent injects new props to the child component, and the 1st assertion "props should not be change in its component and only should be changed by its parent component" is not violated.
Notes:
More info about higher order component can be found in Dan Abramov's article about Presentational and Container Components.
To understand how react-redux connect works - in the online free course, Getting Started with Redux, Dan Abramov shows how to build connect from scratch (lessons 22-29)
state here in mapStateToProps means state in ReduxStore.
It maps Redux state to ReactComponent props. It's not necessarily to map props to states, e.g. Pure Component
mapStateToProps pass state as a props to component using react-redux connect () function. Consider connect() function as wrapper component, which passes props to children.
mapStateToProps
connect (state) -----------------------> component(props)
Related
When do we should use hooks over HOCs, and HOCs over hooks in React?
For example, I can perfectly have a hook for managing auth state, and then use it in a component... but I can also have a HOC which manages the auth state and wrap components for using its logic.
So... is there any rule to know if what interests you is to implement a HOC or a hook?
Why use HOC?
HOC is useful when you want to inject additional behaviors into the existing Component. You can use HOC to inject:
React Lifecycle (eg. execute code in componentWillMount)
State
(eg. react-redux’s connect) 3
Component (Parent Component, Child
Component, Sibling Component) Style
Why React Hook?
If you write a function component, and then you want to add some state to it, previously you do this by converting it to a class. But, now you can do it by using a Hook inside the existing function component.
How exactly re-rendering of the components happen if there is a new state object returned from the redux reducer..?
Are there any optimisation techniques used by react to minimalize the rendering of components ..?
When you connect a component to the redux store, and you map the redux state to props, if a state changes into a new state, the component re-renders. Just like when you pass a state to a child component and that state changes.
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.
I've found mobx observable component only rerender themselves and not their children. How is this achieved?
From the MobX documentation:
MobX reacts to any an existing observable property that is read during the execution of a tracked function.
By using #observer over a component MobX will track and react to changes occurred to observables defined inside the render function of this component.
Each child component should be wrapped with #observer if you wish it to react to changes.
Edited:
By using observer over a component, MobX will override the shouldComponentUpdate by telling the component to update only when necessary (observables change or shallow props change).
From MobX #observer documentation:
observer also prevents re-renderings when the props of the component have only shallowly changed, which makes a lot of sense if the data passed into the component is reactive. This behavior is similar to React PureRender mixin, except that state changes are still always processed. If a component provides its own shouldComponentUpdate, that one takes precedence.See for an explanation this github issue
With Relay, you create a React component as usual:
class TodoApp extends React.Component {
...
}
And then component is wrapped in a Relay container:
export default Relay.createContainer(TodoApp, {
...
});
The Relay container will fetch data using GraphQL and then update the state. This is a higher order component and this state is then passed down as props to its children.
This isn't (or doesn't appear to be) compatible with a flux implementation like Redux. Redux has a single global state object and it too has higher order components that pass props down to presentational components. So I don't see how both the Redux store and Relay containers can coexist currently.
So then how should we update state that doesn't come from the database? How is this state supposed to be managed with Relay?
While I can’t offer you an advice on using them together, technically you can definitely have several higher order components applied one after another:
class TodoApp extends React.Component {
// ...
}
TodoApp = connect(
// ...
)(TodoApp);
TodoApp = Relay.createContainer(TodoApp, {
// ...
});
export default TodoApp;
I’m not sure this makes a lot of sense, but it’s easily doable.
These things are still in discussion and the current state of Redux and Relay may not fit well together if you use a Relay container.
You can join the discussion here
I've done this as follows for a chat application:
The chat component (ChatComponent) is a dumb react component that expects all data to come as props. It also requires the redux dispatch function as a prop so it can dispatch actions when someone wants to send a new message. This is a 'private' component and is wrapped by...
ChatComponentRelay - this renders ChatComponent but is a Relay component which is also connected to the redux store. It uses one of the lifecycle methods (not the constructor) to dispatch the data received via relay into the redux store. This is the component that is used by the rest of the application, and is basically just a proxy to the underlying dumb ChatComponent. It renders ChatComponent passing in all the data in its props from the redux store, and also the redux dispatch function as well.