Parent 范围未触发 child React 中的重新渲染
Parent scope not triggering child rerender in React
我有一个 prent comp 和一个 child cmponent。如下
parent
export class ExpressionMenu extends Component {
constructor(props) {
super(props)
}
state = {
apiArray: [],
}
updateStateFromChild = (arrayType, propertyType, value) => {
let { apiArray } = this.state
let currentArray = []
let idx = apiArray.findIndex((q) => q.id === id)
currentArray = apiArray
switch(propertyType) {
case 'updateObject': {
currentArray = value
break;
}
}
this.setState({
apiArray: currentArray
})
}
render () {
const {
apiArray
} = this.state
return (
<React.Fragment>
<div >
<div>
<ApiPanel
apiArray={apiArray}
updateStateFromChild={this.updateStateFromChild}
/>
</div>
</div>
</React.Fragment>
)
}
}
ExpressionMenu.propTypes = {
styleOverride: PropTypes.object,
eventHandler: PropTypes.func,
};
export default ExpressionMenu;
child
export class ApiPanel extends Component {
constructor(props) {
super(props),
}
removeApi = (id) => {
let { apiArray } = this.props
apiArray = apiArray.filter((q) => q.id !== id);
this.props.updateStateFromChild('api', 'updateObject', apiArray)
};
addApi = () => {
let { apiArray } = this.props
const id = uniqid();
let obj = {}
obj.id = id
apiArray.push(obj)
this.props.updateStateFromChild('api', 'updateObject', apiArray)
};
render() {
const { apiArray } = this.props
return (
<React.Fragment>
{
apiArray.map((apiObj, i) =>
<div key={i} >
<span onClick={() => this.removeApi(apiObj.id) } className={[classes.deleteRow,'material-icons'].join(' ')}>
close
</span>
<div>
<label><b>Hi</b></label>
</div>
<div onClick={this.addApi}>+Add Api</div>
}
</React.Fragment>
)
}
}
ApiPanel.propTypes = {
apiArray: PropTypes.array,
updateStateFromChild: PropTypes.func
}
export default ApiPanel
现在,当我调用 addApi() 时,它会更新 parent 但不会重新呈现 child。
但是当我调用 removeApi() 时,它会更新 parent 并正确地重新呈现 child 组件。
在第一种情况下,当我手动重新加载组件时,我可以看到更改。
不明白为什么会这样
尝试更改您的 addApi
功能。
addApi = () => {
let { apiArray } = this.props
this.props.updateStateFromChild('api', 'updateObject', [...apiArray, {id : uniqid()} ])
};
您需要 return 数组的丰富副本
每当我们使用数组、对象更新状态时。我们需要始终创建一个新数组 [...array],一个新对象 {...obj}。因为如果我们在不创建的情况下更新数组或 obj 中的值,它不会更改参考值,因此它假定状态未更新并且不会重新渲染。
我有一个 prent comp 和一个 child cmponent。如下
parent
export class ExpressionMenu extends Component {
constructor(props) {
super(props)
}
state = {
apiArray: [],
}
updateStateFromChild = (arrayType, propertyType, value) => {
let { apiArray } = this.state
let currentArray = []
let idx = apiArray.findIndex((q) => q.id === id)
currentArray = apiArray
switch(propertyType) {
case 'updateObject': {
currentArray = value
break;
}
}
this.setState({
apiArray: currentArray
})
}
render () {
const {
apiArray
} = this.state
return (
<React.Fragment>
<div >
<div>
<ApiPanel
apiArray={apiArray}
updateStateFromChild={this.updateStateFromChild}
/>
</div>
</div>
</React.Fragment>
)
}
}
ExpressionMenu.propTypes = {
styleOverride: PropTypes.object,
eventHandler: PropTypes.func,
};
export default ExpressionMenu;
child
export class ApiPanel extends Component {
constructor(props) {
super(props),
}
removeApi = (id) => {
let { apiArray } = this.props
apiArray = apiArray.filter((q) => q.id !== id);
this.props.updateStateFromChild('api', 'updateObject', apiArray)
};
addApi = () => {
let { apiArray } = this.props
const id = uniqid();
let obj = {}
obj.id = id
apiArray.push(obj)
this.props.updateStateFromChild('api', 'updateObject', apiArray)
};
render() {
const { apiArray } = this.props
return (
<React.Fragment>
{
apiArray.map((apiObj, i) =>
<div key={i} >
<span onClick={() => this.removeApi(apiObj.id) } className={[classes.deleteRow,'material-icons'].join(' ')}>
close
</span>
<div>
<label><b>Hi</b></label>
</div>
<div onClick={this.addApi}>+Add Api</div>
}
</React.Fragment>
)
}
}
ApiPanel.propTypes = {
apiArray: PropTypes.array,
updateStateFromChild: PropTypes.func
}
export default ApiPanel
现在,当我调用 addApi() 时,它会更新 parent 但不会重新呈现 child。 但是当我调用 removeApi() 时,它会更新 parent 并正确地重新呈现 child 组件。
在第一种情况下,当我手动重新加载组件时,我可以看到更改。
不明白为什么会这样
尝试更改您的 addApi
功能。
addApi = () => {
let { apiArray } = this.props
this.props.updateStateFromChild('api', 'updateObject', [...apiArray, {id : uniqid()} ])
};
您需要 return 数组的丰富副本
每当我们使用数组、对象更新状态时。我们需要始终创建一个新数组 [...array],一个新对象 {...obj}。因为如果我们在不创建的情况下更新数组或 obj 中的值,它不会更改参考值,因此它假定状态未更新并且不会重新渲染。