Reputation: 1840
I have a parent component which has 1 child. I am updating my child by passing data through props. initially, it works fine but when I click on a button and update the state using setState the child gets rendered with old values by the time setState is finished. I have solved it using componentWillReceiveProps in the child but is this the right way?
In the below code if I do setState in filterResults function it won't update the Emplist component .
import React, { Component } from 'react';
import {Search} from './search-bar'
import Emplist from './emplist'
class App extends Component {
constructor(props){
super(props);
this.emp=[{
name:'pawan',
age:12
},
{
name:'manish',
age : 11
}]
this.state={emp:this.emp};
this.filterResults=this.filterResults.bind(this);
}
filterResults(val)
{
if(this.state)
{
let filt=[];
filt.push(
this.emp.find(e=>{
return e.age==val
})
);
this.setState({emp:filt});
}
}
render() {
return (
<div className="App">
<Search filterResults={this.filterResults}/>
<Emplist emp={this.state.emp}/>
</div>
);
}
}
export default App;
EmpList Componet
import React,{Component} from 'react'
export default class Emp extends Component
{
constructor(props){
super(props);
this.emplist=this.props.emp.map(e=>{return <li>{e.name}</li>});
this.next=this.emplist;
}
componentWillReceiveProps(nextProps,nextState,prevProps,prevState,nextContext,prevContext){
// this.props.updated(this.props.empo);
this.next=nextProps.emp[0];
if(this.next)
this.emplist= nextProps.emp.map(e=>{return <li>{e.name}</li>});
}
render(){
if(!this.next)
return <div>name not found</div>
else
return (
<div>
<br/>
<p>The list is here</p>
<ul>
{this.emplist}
</ul>
</div>
)
}
}
Upvotes: 6
Views: 19411
Reputation: 737
If you want to pass from parent to child you can pass using props and if you wan t to do reverse than you can pass one function from parent to child and than use this passed function to send something back to parent.
child will look something like this
class Reciepe extends Component{
render(){
const { title, img, instructions } = this.props;
const ingredients=this.props.ingredients.map((ing,index)=>(<li key={index} >{ing}</li>));
return (
<div className='recipe-card'>
<div className='recipe-card-img'> <img src={img} alt={title}/> </div>
<div className='recipe-card-content'>
<h3 className='recipe-title'>Reciepe {title}</h3>
<ul> {ingredients} </ul>
<h4>Instructions:</h4>
<p>{instructions}</p>
</div>
</div>
)
}
}
parent will look something like this
class RecipeList extends Component{
render(){
return (
<div style={{'display':'flex'}}>
{this.props.recipes.map((item,index)=>(
<Recipe key={index}
title={item.title}
ingredients={item.ingredients}
instructions={item.instructions}
img={item.img}
/>
))}
</div>
)
}
}
Upvotes: 8
Reputation: 281696
Your next and emplist class properties are directly derivable from your props and hence you don't actually need them. You could do it in the following way
import React,{Component} from 'react'
export default class Emp extends Component{
render(){
const { emp } = this.props;
if(!emp || emp.length === 1)
return <div>name not found</div>
else {
return (
<div>
<br/> <p>The list is here</p>
<ul>
{emp.map(e=>{return <li>{e.name}</li>});}
</ul>
</div>
)
}
}
}
However in cases when you do what to make really complex decisions based on props, a combination of componentWillReceiveProps
and componentDidMount/componentWillMount
is the right place to do it.
Upvotes: 0
Reputation: 1290
The problem is that you are assigning the values to this which is not a good practice. Check where to declare variable in React here.
If you are not using the props to do any complex operations. This should work.
EmpList Componet
import React, {Component} from 'react'
export default class Emp extends Component {
constructor(props) {
super(props);
}
render() {
if (!this.next)
return <div>name not found</div>;
else
return (
<div>
<br/>
<p>The list is here</p>
<ul>
{this.props.emp && this.props.emp.map(e => <li>{e.name}</li>)}
</ul>
</div>
)
}
}
Upvotes: 0