Should child components never have a state in React? I understand that state should be maintained by the "wrapper container" or parent container and it should have unidirectional flow. I have started with React and have a header container with upto 10 child components.
Let's say one of the child component is a Form with a submit button that can be enabled or disabled.
Should this child component not be able to have a constructor with state initialized for the button and be able to directly manipulate it or is it important that I maintain states as minute as this in the wrapper container "only"?
You should let the parent container manage the state of forms. I usually attach an onChange listener to each input and then when the submit button is clicked I call a function in the parent component to submit the value contained in the state for my form inputs. The form should only render inputs and do nothing else, basically a dumb component.
The purpose of React is providing a component system to front-end. It does not specify/enforce how state flow. People generally prefer state-less components because it is easier to share and distribute. However, front-end component can never be fully state-less + declarative.
In my opinion, you should feel free to use this.state to manage local state when you feel appropriate.
Related
I am running some tests with react to find out a way for a parent to send an "event" to a child component. In the test application, the parent (CounterController) has a button. When the button is clicked, the parent shall send a reset "event" to the child (Counter) to reset the current count. Like below.
I am new to react, and can not find a way to dispatch/receive events or messages between components. I had a thought to mark the "reset" request as a "state" in the parent, then pass it to the child through props. Then the child clear the "reset" state, through a callback function, to avoid repeating "reset" requests. However, I got the code run into an infinite loop. Here are my codes.
The parent component - CounterController
The child component - Counter
the error logs
I do not feel that I am using react the right way, by asking the child to do something from the parent. Anyway, any idea about how to implement this app in react? How should the data flow be built correctly? Thanks!
You can move up the counter state on the parent ‘CounterController’
and then you pass the counter and setCounter as props to ‘Counter’
You don’t need ‘reset’ state
I am posting my thoughts about using react (as a beginner), and my solution to the app.
treat the react components as the "view" of the application, and maintain the data and controls in the hooks.
create a custom hook to wrap up all data and controls.
create an instance of the custom hook in the top component - display the data in HTML elements and bound controls to buttons to build the app UI
Here are my codes for this simple UI
UI
useCounter hook
counterController component
counter component
Move "count" state from child component (Counter) to parent
component (CounterController).
Pass count state as prop to child component.
Pass increment and decrement methods from parent to child component through props.
Note: Remove reset state, it's not required anymore.
Sandbox link : https://codesandbox.io/s/infallible-platform-vo4qtv?file=/src/CountController.js
I have a requirement where I have to render Component A twice in the Container, one at the top and one at the bottom.
Both the components should be in sync ,
changes made at one place should be reflected at other place,
Component should not mount twice as there's lot of API calls being made inside componentDidMount of Component A.
Is there any approach to do it, without lifting the state up?
Image for the above requirement
A component is an independent entity in react. It has it's own state and own set of variables.
If you don't lift your state to the parent and then pass to the component A.
It is not possible to use same component on same page twice with the same set of state without component being rendered two times.
You must lift state to their parent and then only it can be achieved or else it is not possible.
I have an app with a "menu". The "menu" is fairly complex, and the user can open small divs to set parameters that affect the app in real time. The app is structured as below:
Parent div with multiple useState instances to set parameters
- Menu Child Div
- functions to set those state variables are all passed to this div
- parent state is altered using these
- Main div where the results are displayed
- receives the state from the parent div and displays appropriately
The way that it works is that when the user interacts with the menu, the state is altered in the parent and that state change is then passed in the props to the main child div. This is causing performance issues as the app has to rerender everything when something changes in the menu and the existence of so many state variables may be a problem.
What is the best way to handle this? Using the useReducer function instead could be an option, but I am not sure that this alone would solve the problem. How do I make the main div respond to changes in the menu without everything having to be rerendered?
How do you handle interaction between your menus and your main div without having to re render everything?
Would the performance issues be solved by doing the following?
Parent div does not address state
- Menu Child Div
- interacts with redux state to change options
- Main div where the results are displayed
- reads in and reacts to redux changes
If you want a React component not to re-render unless the local state/props are changed, you may consider replacing your React.Component with React.PureComponent.
Whenever you're dealing with State that is being passed around between component orders, you may want to consider managing a global store. You can do this by using tools such as Redux, MobX-State-Tree, or Context API. This is especially useful if you're managing a mid-large scale project.
Resources:
https://ozmoroz.com/2018/09/what-is-purecomponent/
This resource has some great info on common React tools:
https://www.reactnative.express
And of course, there is always React's docs of which you are likely well aware of:
https://reactjs.org/docs/hooks-intro.html
I'm building an application where I would like to provide separate views for same data.
In my current implementation, data is obtained by web service call and persisted in state of App component in App.js. App component hosts (renders) another component called StackEditor, which acts as a view for this.state.components in App component.
UI elements rendered by StackEditor can be moved around, and to synchronize state of App I do it as below:
<StackEditor
components={this.state.components}
onLocationChanged={this.handleLocationChanged} />
In handleLocationChanged I update the state:
handleLocationChanged(e, data) {
this.setState(prevState => {
// event data copied to state here
return {components: prevState.components};
});
}
As state is now updated, this forces StackEditor to be rendered again, as its property components is bound to state as components={this.state.components} (see in the code snippet above).
This all works, but now I started questioning if I'm doing it right.
Q1: Should I be using state instead of props?
It seems that location of component is mutated in principle, although from StackEditor point of view, it is immutable (I can decide that change is invalid and not to update the state in event listener).
Q2: Is it possible to share part of the state between 2 components in React?
If I somehow convert StackEditor from getting components from state instead of props, will I get notification on state changed by child component (StackEditor) in my parent component (App)?
Q3: Also, are props more convenient to use than state in general?
When I created another component following HOC guidelines (https://reactjs.org/docs/higher-order-components.html) I discovered that props are easily forwarded to "wrapped" component, but not state. If I provide a function to call back via property (as I did above), "wrapped" component can easily call it, without even noticing that it's "wrapped". I don't see how I can easily notify "wrapped" component about state change in "wrapper", without writing some extra code.
If you imagine your application to be a tree of components in a well designed app it's usually like this:
the leafs are stateless components . They decide how data is rendered.
the nodes are stateful components. They decide which components and data to render.
Q1: Should I be using state instead of props?
It depends on which category of components you have (node or leaf).
Q2: Is it possible to share part of the state between 2 components in
React?
If you feel that your app has a lot of state that mutates and needs to be used by several components spread over your tree you usually start to introduce an external state management library (e.g. redux). Components can subscribe to your store and become stateless as your store now handles the state.
Q3: Also, are props more convenient to use than state in general?
They solve different problems so you can't really say that. A stateless component is usually easier to understand but has no capabilities to control anything.
Also read Identify where your state should live and When to use redux.
All that is only a rule of thumb. A lot of the time you will have components that have both state and props because they control parts of your app but delegate other parts to their children.
This all works, but now I started questioning if I'm doing it right.
As far as I can see from the code you provided this looks pretty much as it has to.
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 :)