Reputation: 115
I have problem that render method doesnt run when the props value is changed. What am I doing wrong? I tried using componentwillrecieveprops but it also doesnt run.
ChildComponent:
state = {
data: this.props.populatedWords,
allSelected: false,
res: null,
textAreaVal: null,
editMode: new Array(this.props.populatedWords.length).fill(false),
entityList: [],
selectedEntity: [],
parts: [],
final: null,
entityObject: null,
sendToUpdateEntity: null,
arr: JSON.parse(localStorage.getItem('intents'))[localStorage.getItem('intent')],
selectedValue: null,
textInput: "",
token: JSON.parse(localStorage.getItem('user')).tokens.training
};
componentWillReceiveProps(nextProps) {
console.log("i am called")
// You don't have to do this check first, but it can help prevent an unneeded render
if (nextProps.words !== this.state.data) {
this.setState({ data: nextProps.words });
}
}
render() {
return (
<Card className={classes.root} style={{maxWidth: '100%'}}>
<NoRazmetkaDialog ref={this.dialog}/>
<NoEntityDialog ref={this.dialogE}/>
<HalfRazmetkaDialog ref={this.dialogHalf}/>
<CardHeader action={<Grid container>
<Grid item style={{display: 'flex'}}>
<Tooltip>
<FilterOptions updateSelected={this.updateSelectedValue}/>
</Tooltip>
<TextField variant="standard" style={{paddingTop: '10px'}} onChange={e => {
this.setState({textInput: e.target.value});
}}/>
</Grid>
</Grid>}/>
<div className={classes.tableWrapper}>
<Table className={classes.table} aria-labelledby="tableTitle">
<IntentTableHead data={this.state.data} updateAllSelected={this.updateAllSelected}
allSelected={this.state.allSelected} updateData={this.updateData}
sendToDialogflow={this.sendToDialogFlow} updateEntity={this.updateEntity}
entityObject={this.state.entityObject}/>
<TableBody>
{this.state.data.map((val, i) => {
return (
<TableRow hover>
<TableCell padding="checkbox">
<Checkbox checked={this.state.data[i].checked}
onChange={this.addCheckedPhrase(i)}/>
</TableCell>
{!this.state.editMode[i] &&
<TableCell onClick={this.changeEditMode(i)}>
{val.word}
</TableCell>}
{this.state.editMode[i] &&
<TableCell>
<TextField
multiline
defaultValue={val.word}
className={classes.textField}
margin="none"
variant="outlined"
value={this.state.textAreaVal}
onChange={e => this.handleChange(e, i, 'word')}
/>
<Button onClick={this.changeEditMode(i)}>OK</Button>
</TableCell>
}
<TableCell>
{array[localStorage.getItem('intent')].display_name}
</TableCell>
{this.state.data[i].test === null &&
<TableCell>
Тестировать
</TableCell>}
{this.state.data[i].test !== null &&
<TableCell>
{this.state.data[i].test}
</TableCell>}
<TableCell>
<Select value={this.state.data[i].entity}
onChange={e => this.handleChange(e, i, 'entity')}
inputProps={{name: "data"}}>
{this.state.entityList.map((val, i) => {
return (<MenuItem value={val} key={i}>{val}</MenuItem>)
})}
</Select>
</TableCell>
<TableCell>
<Button onClick={this.updateIntent(i)}>Обучить</Button>
</TableCell>
<TableCell>
<IconButton onClick={this.deleteRow(i)}>
<ClearIcon/>
</IconButton>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</Card>
);
}
Parent component:
render() {
return (
<div>
<PositionedDialog ref={this.dialog} selectedWord={this.state.selectedWord} textAreaVal={this.state.textAreaVal} updateRes={this.updateRes}/>
<IconButton variant="contained"
color="primary"
component={Link} to="/app/intent"
onClick={this.backToComponent}
>
<KeyboardArrowLeft/>
</IconButton>
<Paper>
<Toolbar>
<Grid container alignItems="center">
<Grid item xs alignItems="center">
<TextField
fullWidth
onFocus
id="help"
InputProps={{
disableUnderline: true
}}
value={this.state.textAreaVal}
onKeyPress={e => {
if (e.key === 'Enter') {
this.findSelectedText();
}
}}
onChange={e => {
this.setState({textAreaVal: e.target.value});
}}
/>
</Grid>
</Grid>
</Toolbar>
</Paper>
<Paper style={{marginTop: "20px", overflow: "hidden"}}>
{this.state.generator > 0 && this.state.populatedWords !== null &&
<IntentTable populatedWords={this.state.populatedWords}/>}
</Paper>
</div>
);
}
this.state.data form a table. and when my this.props.words is updated it does not add row to the table. I see that the problem is with it.
Upvotes: 0
Views: 623
Reputation: 16122
to avoid using lifecycle methods, don't save your props to state in your child component. Remove data
and editMode
from state.
In your child render access the props directly
render() {
const data = this.props.populatedWords;
const editMode = new Array(this.props.populatedWords.length).fill(false);
...
}
Upvotes: 0
Reputation: 88
First of all, I think you should be using getDerivedStateFromProps as componentWillReceiveProps is deprecated.
To address your issue, regarding your componentWillReceiveProps, it appears you're comparing this.state.data
of your child with nextProps.words
, yet it appears to me you're sending : <IntentTable populatedWords={this.state.populatedWords}/>
so your prop name is populateWords
. Try changing this and keep me updated!
Upvotes: 0