A function component does not perform its visual update when the state changes.
I provide a minimal example of my component where I set a new state but the component does not update in the browser.
import * as React from "react"
import { Button, makeStyles, Grid, TextField, createStyles } from '@material-ui/core'
import ReactDOM from "react-dom";
const styles = makeStyles(theme => createStyles({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
},
button: {
margin: theme.spacing(1),
}
}))
export interface RTestData {
title: string
}
interface Props {
data: RTestData[]
}
const testData: RTestData[] = [{title: "AA"}, {title: "BB"}, {title: "CC"}, {title: "DD"}, {title: "EE"}]
export const RTestContainer: React.FunctionComponent<Props> = (props) => {
const [count, setCount] = React.useState(0)
const [data, setData] = React.useState(props.data[count])
const classes = styles()
const handleClick = () => (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
console.log(`BUTTON click`)
const target = e.target
setCount(count + 1)
setData(props.data[count])
console.log("data " + JSON.stringify(props.data) + " ->" + JSON.stringify(data))
}
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<RTestForm title={data.title}/>
</Grid>
<Grid item>
<Button
variant="contained"
color="primary"
className={classes.button}
onClick={handleClick()}
>
Next!!
</Button>
</Grid>
</Grid>
)
}
export const RTestForm: React.FunctionComponent<RTestData> = (props) => {
const [title, setTitle] = React.useState(props.title)
const handleChange = () => (e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target
const value = target.value
console.log("Title change ->" + title)
setTitle(value)
}
const classes = styles()
return (
<form className={classes.container} noValidate autoComplete="off">
<Grid container spacing={2}>
<Grid item xs={12} sm={6} lg={6}>
<TextField
required
label="Title"
value={title}
onChange={handleChange()}
className={classes.textField}
margin="normal"
variant="filled"
/>
</Grid>
</Grid>
</form>
)
}
ReactDOM.render(<div id="root">
<RTestContainer data={testData}/>
</div>, document.getElementById('root'));
A click on the button should select and display the next data item, e. g. the textfield displays "AA", "BB" and so on.
On handleClick
you change RTestContainer
state but it doesn't affect RTestForm
state.
// v On handleClick changes `data` state
<RTestForm title={data.title} />
// Changing props won't re-initial the state. v
const [title, setTitle] = React.useState(props.title);
Try adding a listener for props.title
change with useEffect
:
export const RTestForm: React.FunctionComponent<RTestData> = props => {
const [title, setTitle] = React.useState(props.title);
React.useEffect(() => {
setTitle(props.title);
}, [props.title]);
return <>...</>
};