react component's data state vs. props - reactjs

I know the main concern about when to put something on the state or receive as props, but what about when I have something that is suitable for both? I have items that should be 'active' when the parent is active(props) and also have the option to toggle this attribute from a click event(state).

It sounds like what you want is something like a parentActive variable held in the state of the parent and passed as a prop to the child(ren). Then a childActive variable held in the state of the child that is toggled by your click event. Then you'd simply have some logic / a conditional within the child that determines whether it's active. For example:
// Within child component
if (this.props.parentActive || this.state.childActive) { }
In general, when you have a new value that needs logic, you store it in state, create the click handlers that you need within that component, then pass it off (and possibly its click handler) as a prop for children. In your case, you need logic for a value/active flag within the parent, and logic for a value/active flag in the child.. so it sounds like you would want to set state in both of them, and pass the parent value as a prop for the child.

Related

How to pass data from grandchild to parent component in React?

I have a form (Parent) which contains an input field (Child), which gets its value from a reference table (Grand-grand-child) that is displayed as a modal (Grand-child) which opens up by clicking a button attached to the input field. This is a nested structure that roughly looks like this:
I need to set the value of the input field by selecting a row in the reference table and confirming my choice with a button "SET VALUE", which means I need to pass data three levels up from Grand-grand-child to Parent through Grand-child and Child.
My state is kept in the Parent component. Is there a simple way of achieving that without using external libraries? Please offer a solution using Hooks as all of my components are functional components.
Here is the code: https://codesandbox.io/s/festive-fast-jckfl
See CreateRate component where:
CreateRate.jsx is the Parent
InputField.jsx is the Child
DataFetchModal.jsx is the Grand-child
Airports.jsx is the Grand-grand-child
Pass a change handler function from parent (where state lives) down to the grand child. The grand child should call this change handler when clicking the Set Value button.
If this is too much prop drilling
look into component composition first
if that doesn’t work out, look into context api
Update:
You mentioned your problem was trying to access the state inside Grand-grand-child from your Grand-child. In this case you can lift the state up (to Grand-child). This means lifting 'airports' up to DataFetchModal. Here is more info on lifting state.
https://reactjs.org/docs/lifting-state-up.html#lifting-state-up
Also, it appears you are running into these problems because your code is very nested and not very composable. I would suggest looking into how you could better break up your components. One way to accomplish this is using compound components.
https://kentcdodds.com/blog/compound-components-with-react-hooks
Determining how to break this up better would take some time. However, just looking at this briefly. You may be able to move your DataFetchModal to your parent. Pass a callback to the InputField to fire it off and send the identifying parameters (what input called it). Then, from the parent, compose in whatever modal body using composition. It appears you have a lookup object (objType) inside DataFetchModal. Maybe this could go away by using composition (not sure, and probably separate topic).
Update 2:
I pulled down your code sandbox and made a few changes that may help access parent level state. I moved the modal into the parent. Check it out.
https://github.com/nathanielhall/Test

React: How to use getDerivedStateFromProps() to set component state. It interferes with controlled component that uses the same state variable

I have a component that receives a variable as a prop.
The getDerivedStateFromProps() is typical, meaning that when nextProps.someProp doesn't equal prevState.someStateVar, that prop is assigned to state variable.
I also have a Controlled element - an HTML text Input element which is associated with the same state variable.
The problem is, when I change the state variable through the controlled element, getDerivedStateFromProps() executes and sets the value back to the prop received earlier.
As a React novice, I don't understand why this happens. The above action should only occur when a new prop value is received, like the name 'nextProps' suggests.
Please suggest how to get the desired behaviour:
Use prop to set initial state
Let my controlled element (html input tag) set next values of the state variable
iff new prop value is received, assign that to the next value of the state variable
The article - "You Probably Don't Need Derived State" was true.
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
I referred the controlled component email example.
Now, the data of all the child components is stored in the parent's state.
The parent's state is passed down as a prop to the child components.
A method in the parent component edits the state variables. This method is passed down to the child components as a prop.
Hence, the single source of truth is established and it is stored in the parent component making its children fully controlled components. This is how I did it.

react - reset child component from parent

I need to reset a child component from parent. I know the best way is to send a props. So I send reset = true as properties. But looks like I need to have a callback function to parent from the child to change that properties to false after reset is done, so if it happens again, the rest works.
I do not want to use refs as it is not the best method, but I do not want to have callbacks too.
What other suggestion you would have?

In reactjs, are props pass by value or pass by reference?

As far as I can tell, if I pass a parent component state down to a child, then that child gets the live state of the parent.
So a change made in the state of the parent is immediately also available in the child via the prop that it came on.
Is this correct?
It's basically the same mechanism as anywhere else in the language, as you'd expect. Primitives are passed by value and variables that aren't primitives will be passed by reference.
React takes care internally of the updating of props, so that children always have the most up-to-date value of the prop.
This is the lifecycle method that is called when receiving new values for props.
However, make sure you respect the infrastructure put in place and the exposed API that React gives you.
Short answer: props are passed by reference.
The reason it can be confusing: if you change the parent's state by hand (bad practice!), the object will change in the child component, too. But won't trigger re-render! (The child component won't "know" that its props has changed.) So you won't see the UI change.
However if you change the parent's state with setState (the preferred practice), the child will be notified, that it must re-render itself.
If you pass down the state of the component as props to its child, then if the state of the parent component changes it re-renders, which will also re-render its children with the refreshed properties. The children don't directly listen for the state change like the parent does, they are simply re-rendered as as result of its parents state change and updated.
Take a look at this - https://facebook.github.io/react/docs/multiple-components.html. It will help you get your head round how this concept works. Hope this helps!
When the state of a component is changed, then the component is re-rendered by React. While doing that , its child components are also re-rendered, which causes changes in them also.
No, they will not be duplicated, you will access to those props by reference, because they come from a single object wich defines them, and then pass them as a reference to the child objects.
You can take a look to the official documentation here: https://reactjs.org/docs/react-component.html.
I suggest to use a stateless mechanism to handle large data, expecially if shared.
Personally I use mobx (https://github.com/mobxjs/mobx) wich is a great framework to create stateless apps.
With this method you can handle data and state updates in a single component, called Store, and use components to render html only, and not to handle data, wich is a great boost on application performances.

Set React component state from outside of component

I have a list of components and want to set each component as selected when the user clicks on it.
The flow looks like
Dashboard
⎿ MyList
⎿ MyItem -> onClick -> setState({active:true})
I've got the selected part done by using state but I'm left wondering how to deactivate all the other elements.
By definition, state is not accessible from outside the component.
And always copying props to state is not recommended.
In your component tree structure. you should set the selected item as state in the parent (not in the item).
And pass the selected Id to each item as a prop.
In the child render, you can do something like
let itemIsSelected = (this.props.itemId == this.props.selectedId);
And pass a method from parent to child, and then include that as:
onClick={() => this.props.setSelected(this.props.itemId)}
In the official docs, there is a good explanation on how to structure components. This may be helpful to determine whether something should be state or props, or whether stuff is better managed inside child or parent.
Dan Abramov mentions another clever way to access a state change from outside a component class. Technically the setState function still has to be called from within the component class anyway, so it's not REALLY outside the component, but this allows you to set the state of different components in the same fashion if you want, from the returned value of a function.
Basically, you can pass in a function into the setState() function, and the state will be set to the returned value of that function.
you can see his post here:
https://twitter.com/dan_abramov/status/824308413559668744?lang=en

Resources