How to get state data from child to parent component? - reactjs

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:

Related

how to update both parent and child state before render without extra renders in React 15

If I use setState in the child and place a callback in the parent to update the parent state that propagates to child props, then I end up with two render calls.
One for the update to the child state, and one for the prop changing. I can manually use shouldComponentUpdate to ignore the prop change if I want, but the render won't be ready until the state updates.
I know all this can be done easily in react 16-18, but migrating is not simple at the moment.
I am wondering if the solution is to make the child state the source of truth. I can solve all my problems this way, but I thought in react you typically made the parent the source of truth.
Parent Component
Child Component
ChildComponent
function = () => {
this.setState ( {updatedStateProperty}, callback())
}
ParentComponent
callback = () => {
this.setState ( {propSentToChild})
}
What happens is the child component changes state, then render occurs, then the callback occurs, prompting another render.
I want to either
A. change child state, then have the callback called before render
or
B. update child state, then ignore the parents passed props
I can do B, but I'm unsure whether it is proper form to basically make the child's version of the shared state the source of truth
I think you're kind of close. What you really want to do is pass the state to the parent, handle setting the state there, and let the new state trickle down to your child component via props. This is a fairly common pattern for react.
class Parent extends React.Component {
constructor() {
this.state = { foo: "bar", bing: "baz" }
}
stateUpdater(newState) {
this.setState({ ...this.state, ...newState });
}
render() {
return <Child
prop1={this.state.foo}
prop2={this.state.baz}
stateUpdater={this.stateUpdater}
/>
}
}
class Child extends React.Component {
handleClick = () => {
this.props.stateUpdater({ foo: 'bazaar' });
}
render() {
return <div>
The foo is {this.props.foo} and the baz is {this.props.baz}.
<button onClick={this.handleClick}>Click Me!</button>
</div>
}
}

How to make functional component rerender properly on parents state chage?

please help me figure out why the component works like that.
I have a functional component something like this:
function MyComponent(props) {
const { dataArr } = props;
[ownDataArr, setOwnDataArr] = useState([...dataArr]);
// doesn't change after changing in the state of the parent component
console.log(ownDataArr);
return (
// ownDataArr is used here
);
It receives dataArr from parent component via props (parent component contains this in state). And when changed in parent component after MyComponent rerenders, ownDataArr stays the same. What am I doing wrong?
P.S. The child component needs the state, since it must be able to change the received data without constantly sending it to the parent.
You can do this to update the state on props change
useEffect(() => {
setOwnDataArr(dataArr)
}, [dataArr])
This is because state initialize on the first render of component with the props and when the props change, we have to update the state using useEffect
function MyComponent(props) {
const { dataArr } = props;
[ownDataArr, setOwnDataArr] = useState([...dataArr]);
// add useEffect wich depend on dataArr changing,
// because initial state is memoized by useState
useEffect(() => setOwnDataArr(dataArr), [dataArr])
return (
// ownDataArr is used here
);
}

How to mock data with props in your React Functional Component

In my React application, i am developing a screen using Functional Component.
I want to populate the data on the screen with mock data until my API is ready. I basically have an Accordion with open state where i want to display the names. Right now, i am hardcoding name to populate that. Later, i will be replacing with the actual data coming from Store. So to do that i am defining the hard coded data like below in my component itself as after the API is ready, my props will have all the required data.
function MyComponent (props) {
props={
history: {},
data:[
{
name:’XYZ’,
},
{
name:’ABC’,
}
]
}
return (
<div>Content goes here </div>
)
}
This throws me error. I want to understand if i am doing this correctly as i need to read the data values inside my div.
Props are immutable, so you should not change them.
Instead, you could mock the props that you are passing to MyComponent
Example:
In the parent component:
function MyApp() {
const mockProps={
history: {},
data:[
name:’XYZ’,
]
}
return <MyComponent {...mockProps}/>
}
and in MyComponent
function MyComponent (props) {
// do something with props here
return <div>Content goes here </div>
}
It is probably best to mock this data as coming from parent container, that way when you add Redux library later, you can simply change /where/ props are being sent from.
e.g
in Parent JS:
const Parent = props => {
const [accordionData, setData] = useState(['#1', '#2', '#3'])
/ ... rest of component /
return <Accordion accordionData={accordionData} />
}
in
const Accordion = props => {
const { accordionData } = props // pull props from parent component.
const mapAccordionData = accordionData.map(el => { return <div key={el}>el</div> })
return mapAccordionData
}
Something like this should work.
ParentJS is feeding the accordion an array of data via parent->child props. Later this will be store->child props. Accordion (child) is then rendering that data to so the user can see it via divs.
You would pass props into a component. They should come from either a parent's component state or a store (like Redux store).
function MyComponent(props) {
return <div>{props.hello}</div>;
}
class ParentComponent extends React.Component {
state = {
hello: 'Hello World!',
}
render() {
return <MyComponent hello={this.state.hello} />;
}
}
You can also pass a function that changes the state of the parent making the props also change for MyComponent. It won't mutate them but rather return a new state and therefore pass a new set of props.
Let me know if you need any further explanation.

Redux: Update parent component data after child operations

I have some data loaded in the store after initial Axios call.
Then I render two components match (parent component) and player (child component).
This is the way to show the two components in a related way (this is a simplified example from my original code, in this example I could solve my problem in another way, but in my complex real code it is essential to do an operations in children component first):
match.js
class Match extends Component {
constructor(props) {
super(props);
}
render() {
return (
Object.values(this.props.matchs).map(( match_id ) => {
let match = this.props.matchs[match_id];
return (
<div key={match_id}>
<p>{match.tournament}</p>
<p>{match.color}</p> {/* this color depends of children condition*/ }
<div className="players">
{match.array_players.map ( ( player_id ) => {
let player = this.props.players[player_id];
return (
<Player key={odd_id} ownPlayer={player} />
)
})
</div>
</div>
)
});
)
}
}
const mapStateToProps = state => {
return {
matchs: state.matchs.matchs,
players: state.players.players
};
}
const mapDispatchToProps = dispatch => {
return {
// actions
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Matchs);
player.js
class Player extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<p>{this.props.ownPlayer.name}</p>
<p>{this.props.player_color}</p>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
// I need to make some previous operations before render
let player_color;
if (ownProps.ownPlayer.name == "paul")
player_color = 'yellow';
else
player_color = 'blue';
// Then I Need to update parent component with children color condition
// if (player_color == 'yellow')
// match_color = 'yellow'
//
// Call some action here to update parent component???
// things like these do not work:
// let id_p = ownProps.player.id_player;
// state.players.players[id_p].color = 'blue'; This does not work
return {
player_color
};
};
const mapDispatchToProps = dispatch => {
return {
//
}
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Player);
Then I need to update a prop in a parent component after some conditions in children component.
I've read this article:
https://redux.js.org/docs/recipes/ComputingDerivedData.html
But I don't know how to send data to store and refresh parent component before render.
I thought about calling like an action in componentWillMount or componentWillUpdate to send data to store, but I don't know if it's correct way.
There is nothing wrong with calling an action inside the lifecycle, it is not recommended to do it inside the render method because it my trigger infinite actions, but in your situation if you indeed have to do this calculation inside the child component I believe you should dispatch this action inside componentWillReceiveProps or ComponentDidMount, in some situations you actually have to do it in both places.
go for it!
The docs are pretty clear:
You can either do one-time ops in constructor / ComponentWillMount / ComponentDidMount or repetitive ops in recurring life-cycle methods like ComponentWillReceiveProps.
If you need a way for the child component to update the store, than you have to dispatch an action that will go and do so, and put it in ComponentWillMount or ComponentWillReceiveProps depending on the need, sometimes you need to put it in both.
But, on a side note, like Bruno Braga said, it does seem like the wrong place to put logic in.
I would suggest to put this logic in the reducer, as Component really shouldn't handle store logic, just notify (dispatch) state changes.
Also, I don't think that you need to connect the Player component to the redux store, since it seems like each player has it's own independent instance.
What I would suggest is passing the Player Component a function from the Match Component, something like
<Player ... onGoalScored={()=> this.handleGoalScored()} />
and on the Match component do:
handleGoalScore() {
this.props.dispatch(updateGoalsAction())
}
and have the logic in the reducer, the let's say will figure out what the color of Match should be, and, on the next state update to Match, because of the binding to store.matchs.color will be rendered as Red

What is the proper way to handle React state and props

I've been using React for a while, and I've tried many different approaches to do this, they all have their advantages and disadvantages so I'd like to clarify which one is the way to go.
So I have this example scenario:
- A (smart) parent component, listening to a flux store
- A (dumb?) child component being rendered by the parent component above only rendering a view and having some "small internal logic", and by that I mean, some logic that doesn't make sense to be handled by an external action, like onChange events that update its input value, for example.
Should I only pass whatever I wanna pass to the child component as props, and don't mess with its state. So whatever small logic I need to do I update its props directly (even tho I know it's not recommended to update props directly)?
Or
I pass whatever props I wanna pass to the child component and then "get them" in the getInitialState, do that small logic using its now state variables?
The problem with the second approach is that when I actually send an action from the child component, and the parent component listens to the stores results and gets updated, and I have a hard time re rendering the child component now, unless I change its key value, which I also think it shouldn't be done this way.
And the first approach, even tho I'm changing props, which, like I said, I don't think it's also the best thing to do this, I don't have a problem re rendering the child component after sending an action that updates the store that the parent component is listening to.
Probably there are other ways to do it, and for sure a better way. And that is what I'd like to see. Let me know if the question is confusing and I'll try explaining in some other way.
Thanks!
You should only set state from the main (parent) component. All children components should be "dumb" components. If you need to manipulate state from a child component...have a function in the parent component that modifies the state needed...then pass that function as a prop to the child. When the action needed to update the state in the child is completed, call the function passed in as a prop which will call it in the parent component and will update state accordingly.
Below is just some boilerplate code to give you an idea as to what I'm talking about.
Example child component:
import React, {Component} from 'react';
class Child extends Component {
edit = () => {
var state = "string";
this.props.edit(state);
}
handleChange = (evt) => {
this.props.inputChange(evt.target.value);
render() {
return (
<button type="button" onClick={this.props.edit}>Click Me!</button>
<input type="text" name="name" onChange={this.handleChange}>
)
}
}
export default Child;
Example parent component :
import React, {Component} from 'react';
import Child from './Child';
class Parent extends Component {
edit = (val) => {
this.setState({data: val})
}
inputChange = (val) => {
this.setState ({input: val});
}
render() {
return (
<Child edit={this.edit} inputChange={this.inputChange}>
)
}
}
export default Parent;

Resources