I was using a stateful component but upon making it stateless I am unclear how/if I can toggle inner fields:
Here's a contrived example. I am actually working with react-redux-form and need to toggle certain input fields based on some radios.
const Sample = (props) => {
let show = true
const toggleMethod = (model, value) => {
show = !show
}
return (
<div>
<Control changeAction={toggleMethod} />
{ show === 'cc' ? <CCFIelds /> : null }
</div>
)
}
The toggle method works great but it will not rerender. Am I obliged to use state for this or is there a way to do it as is?
When #Jason Xu say you can dispatch to change state, it's a way to influence parent and cause rerender, but you don't have to redux.
The easiest way is to let parent (smart container) own and control the show variable, and then pass to your stateless component as a prop. Define the toggleMethod() in parent, and pass down also.
To summarize:
show toggled in parent
prop changes
stateless component rerenders
Related
I have a parent function component which has a boolean (which is set via child component and also used to render some container on parent component).
Is the below setup fine in terms of updating and dynamic rendering based on isSomeBoolean?
const [isSomeBoolean, setisSomeBoolean] = useState(true);
const updateIsSomeBoolean = (boolVal) => {
setisSomeBoolean(boolVal);
}
<ChildComp updateIsSomeBoolean={updateIsSomeBoolean} />
{isSomeBoolean && (
<div className="container">
....
</div>
)
}
In the child component, somewhere I invoke the parent function as below;
props.updateIsSomeBoolean(false);
Yes, Passing state and controller function to the child component is very normal in react.
But always keep in mind that changing state in parent component will render both components so keep the state near to component where is it required.
In your scenario, you're going in the right direction.
Is there a way to DISPLAY props on parent component in React?
Is this similar to passing props from child component to parent component?
React and many other modern frameworks (like Vue) have what they call a top-down data flow:
This is commonly called a “top-down” or “unidirectional” data flow.
Any state is always owned by some specific component, and any data or
UI derived from that state can only affect components “below” them in
the tree.
If you imagine a component tree as a waterfall of props, each
component’s state is like an additional water source that joins it at
an arbitrary point but also flows down.
What you can do instead is supply the child component with an event listener and update the parent component's state accordingly.
const ParentComponent = () => {
const [parentState, setParentState] = useState(null)
return (
<ChildComponent
onTextChange={(newState) => setParentState(newState)}
value={parentState}
/>
)
}
const ChildComponent = ({ onTextChange, value }) => {
return <input type="text" value={value} onChange={onTextChange} />
}
I have a div which has some class "xyz" at initial state.
Now some change occurs inside my global redux state and I got the props in render method like
render(){
if(this.props.privateMode) { div.class = "abc"; }
return ( <div/> )
}
Is this the right way to update a class for a div when something changes on the global state ( redux ) ?
This is a two part issue.
How to handle the class update.
The className update see the above answer.
How to handle the rerender of the app
Anytime the redux store is update it triggers a rerender of the application. You can grab those updates directly in the render method as the props will be updated. Or in the componentWillReceiveProps method you can get the nextProps and compare them to the current props and decide if you wanna handle it in a certain way.
const { privateMode } = this.props;
<div className={`test ${privateMode ? 'abc' : 'xyz'}`}>
...
</div>
Or use Classnames package
const privateModeClass = className('test', {
'abc': privateMode,
'xyz': !privateMode,
});
<div clasName={privateModeClass} />
I have two components, TabTble and MultiSelect.
I'm rendering MultiSelect component in TabTble, so parent component is TabTble and child component is MultiSelect.
I have some state in my child (MultiSelect) component, how to get it in TabTble component.
const selectedData = this.state.multi; this is state data
const {selectedData } = this.props in this way i passed it as props
<MultiSelect selectedData ={ selectedData } /> And render it in child component like this.
The correct way of sharing state variables between components is through redux store. The major advantage is if you have more than just 2 components, then u can use store state in all of them and modify it by dispatching actions which again will make the modified state available to all the components.
you can do like this suppose you have these two components :
class TabTble extends Component {
handleChildData = (fromMultiSelectData) => {
//Do whatever you want to do from this child data
}
return (
<MultiSelect selectedData ={ selectedData } handleChildData = {this.handleChildData}/>
);
}
wherease in MultiSelect component:
class MultiSelect extends Components {
state = {
localData:[] //local state data which we want to send to parent components
}
handleClick = () => {
let {localData} = this.state;
this.props.handleChildData(localStateData)
}
render(){
let {selectedData} = this.props;
return(
somechild
//Note you need some event handler like onChange,onClick to pass this data up
<div onClick={this.handleClick}>Send Data to parent</div> //you can pass any other data from here
)
}
}
// Note this design pattern is not good while designing react code. Its always recommended when you have such prop drill down or use good state management either context api or redux.
I think you should change a bit your code. Put the states who goes to change in Parent and pass it as a props to child, in child you can change the state.
If u are not using Redux I think it is the right way.
See that example:
I just wonder if it is good that the child component updates the parent component.
in the source code, like following
class Parent extends React.Component{
state = {
name : ''
}
changeState = ((state) => {
this.setState(state)
})
submit = (() => {
// send state to api..
})
render(){
return(
<div>
<Child changeState={this.changeState} {...this.state}/>
<button onClick={this.submit} />
</div>
)
}
}
class Child extends React.Component{
change = ((e) => {
this.props.changeState({
name : e.target.value
})
})
render(){
return(
<input onChange={this.change} value={this.props.name} />
)
}
}
the reason I use this way is submitting method.
There are many input tags, and I want to bind them all together.
but I'm not sure this way is good or not.
because when I type something, parent component always will rerender.
I think it is not good.(actually it just my thinking...)
is it right?
I have used this way to update state of a parent from a child. It does work properly. But it makes the components little complex.
In your case (assuming you do this for text input elements) I don't think this will be a good practice if you are doing it for tiny input components. Because every time you hit a key on a keyboard the parent component will try to update.
But if you are wrapping a set of input elements and pass a larger object to a parent component I think that will be fine.
You could use react life cycle method shouldComponentUpdate() method to control the rendering of the parent component
shouldComponentUpdate
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
shouldComponentUpdate(nextProps, nextState) {
if (this.props.name != nextProps.name) {
return true;
} else {
return false;
}
}
Here nextProps refers to the props you receive(updates) and you can refer to current prop values by "this.props"
And return true to render and false to skip the rendering.
If you have perform validations when the user inputs, then its ok.
Otherwise change 'onChange' event to 'onBlur'
Its a good idea to lift the state up and update it in the parent if multiple other siblings want to refer to the same values. You can optimise on this my making your Parent and Child Components pure as long as they don't have complex and deeply nested props and states.
According to the React docs:
React.PureComponent is exactly like React.Component, but
implements shouldComponentUpdate() with a shallow prop and state
comparison. If your React component’s render() function renders the
same result given the same props and state, you can use
React.PureComponent for a performance boost in some cases.
Re-rendering of parent is not a problem as long as it is not wasted. And Unless you are using Redux, I think this is a proper way to manage the state, i.e., inside the parent component and updating it using the child. In this way, you have made your form into a controlled component.
I think the following page will be useful to you: https://scotch.io/courses/getting-started-with-react/parent-child-component-communication