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
Related
Hello all you fellow coders out there. I'm fairly new to react and I'm wondering what is the best way to handle a situation as follows:
My root component has a form which defines at submit which list of objects it should pass to the child component to map and render. However after the objects are set as a state of the root component and passed to the child component as it renders it will be unable to map as the state isn't yet updated and is undefined because of this.
So anyway what is the right way to tackle this?
I fixed the issue via an if statement which returns null if the list of objects isn't set. Is this the right way to go about it though?
I am current working with some complex stateful React components I installed through npm. For example, a react-bootstrap-table component. It accept data through its props. But it keeps a lots of states of its own, for example, which row is currently selected. I am adding a button, on clicking I would like to clear all the selected row information. Not having access to any API that can do that, I am wondering if I can totally reset the table component.
Right now I use a wrapper component that render the table based on a flag. It looks like:
class wrapper extends React.component{
render(){
if(this.props.flag==true) return <React-Table />;
else return null;
}
}
Now by toggling the flag, I can force a re-render of the table component with its original state.
I am wondering if there is a more straightforward way to do this?
After searching the react-boostrap-table API, it found a method reset (see docs):
Call reset to clean all the status on the table currently.
this.refs.table.reset(); // this.refs.table is a ref for BootstrapTable
To give a more general answer,
React does not have a general way to reset a component externally, the component should provide it if it's necessary. There are 2 ways for parent component to communicate with child component, through props, or not frequently, using ref to directly call a child method. Resetting is using the second way.
For react-bootstrap-table, there are reset() and cleanSelected() method you can call. How to call child component method.
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.
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.
I have a YouTubeiFrame react component that renders an empty div and then drops the YouTube iframe player in to that div using componentDidMount. All works fine. I have a cueVideo method defined on the component which uses the players
API to cue new videos:
cueVideo(videoId) {
this.player.cueVideoById(videoId)
}
In different places in my app you can click a button or some another action to indicate that you want to play a new video. When you perform this action the 'currentVideo' state is updated via redux and as a result the YouTubeiFrame component receives the new video id as an updated prop.
My question is how to call the cueVideo method above in reaction to the updated prop. I've considered using shouldComponentUpdate to compare this.props.currentVideo with the next props
but concious this method is really supposed to return true/false so the render function can be called. All I want to do is call cueVideo when the currentVideo prop changes - I don't really need to re-render.
What's the best way to do this?
All I want to do is call cueVideo when the currentVideo prop changes - I don't really need to re-render.
When new props are received, React will automatically call render() to update your component. Once all the updates have been flushed to the DOM, React will also call componentDidUpdate() on your component to give you an opportunity to respond to the changes. As the documentation says:
Use this as an opportunity to operate on the DOM when the component has been updated.
I would suggest this is the perfect place to call your code as needed.