Reactjs 如何在父级状态更改时防止子组件重新渲染
我有两个无状态组件和一个有状态组件。在我的有状态组件中,我有一个人员列表,当我单击其中一人时,它会打开一个模式。我基本上将模态的状态存储在有状态组件中,并将值作为道具发送给模态。因此,它在任何时候打开模型并重新渲染所有内容时都会更改状态 如何防止在更改状态后重新呈现无状态类 我在我的无状态组件中尝试了memo,但没有成功 模态分量Reactjs 如何在父级状态更改时防止子组件重新渲染,reactjs,frontend,Reactjs,Frontend,我有两个无状态组件和一个有状态组件。在我的有状态组件中,我有一个人员列表,当我单击其中一人时,它会打开一个模式。我基本上将模态的状态存储在有状态组件中,并将值作为道具发送给模态。因此,它在任何时候打开模型并重新渲染所有内容时都会更改状态 如何防止在更改状态后重新呈现无状态类 我在我的无状态组件中尝试了memo,但没有成功 模态分量 const modal = React.memo((props) => { return ( <Modal show={props.sh
const modal = React.memo((props) => {
return (
<Modal show={props.show} onHide={props.handleClose} aria-labelledby="contained-modal-title-vcenter"
centered>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={props.handleClose}>
Close
</Button>
</Modal.Footer>
</Modal>
)
});
export default modal
const model=React.memo((道具)=>{
返回(
模态标题
呜呜,你正在以模态的方式阅读这篇文章!
接近
)
});
导出默认模式
人成分
const person = React.memo((props) => {
console.log("render");
return (
<article className="Person" onClick={props.clicked}>
<Container>
<Row>
<Col>
<p style={{marginBottom: 0 + 'px', marginTop: 1 + 'rem'}}><b>{props.name}</b></p>
<div className="Organization-wrapper">
<FontAwesomeIcon className="Organization-icon" icon={faBuilding}/><p>{props.company}</p>
</div>
</Col>
<Col>
<div>
{
props.image ?
<img src={props.image} height="50" width="50" className="Person-image"
alt="avatar"/>
: <svg height="50" width="50" className="Person-image">
<rect fill="cornflowerblue" x="0" y="0" height="50" width="50"/>
<text
fill="#ffffff"
fontSize="20"
textAnchor="middle"
x="25"
y="30">{props.first_char.toUpperCase()}</text>
</svg>
}
</div>
</Col>
</Row>
</Container>
</article>
);
});
class PersonList extends Component {
state = {
persons: [],
show: false
};
componentDidMount() {
axios.get('')
.then(response => {
const result = response.data.data.slice(0, 5);
this.setState({persons: result});
});
}
personSelectedHandler = (id) => {
this.showModal();
};
showModal = () => {
this.setState({ show: true });
};
hideModal = () => {
this.setState({ show: false });
};
render() {
const persons = this.state.persons.map(person => {
let avatar;
if (person.picture_id != null) {
avatar = person.picture_id.pictures["128"];
}
return <ListGroup>
<ListGroup.Item>
<Person
key={person.id}
name={person.name}
company={person.org_id.name}
first_char={person.first_char}
image={avatar}
clicked={() => this.personSelectedHandler(person.id)}
/>
</ListGroup.Item>
</ListGroup>
});
return (
<div className="Wrapper">
<Modal show = {this.state.show} handleClose = {this.hideModal}/>
<Header/>
<div className="Breadcrumb">
<h4 className="Breadcrumb-text"><b>People's List</b></h4>
<hr/>
</div>
{persons}
</div>
);
}
}
export default PersonList;
const person=React.memo((道具)=>{
控制台日志(“呈现”);
返回(
{props.name}
{props.company}
{
道具,形象?
:
{props.first_char.toUpperCase()}
}
);
});
有状态组件
const person = React.memo((props) => {
console.log("render");
return (
<article className="Person" onClick={props.clicked}>
<Container>
<Row>
<Col>
<p style={{marginBottom: 0 + 'px', marginTop: 1 + 'rem'}}><b>{props.name}</b></p>
<div className="Organization-wrapper">
<FontAwesomeIcon className="Organization-icon" icon={faBuilding}/><p>{props.company}</p>
</div>
</Col>
<Col>
<div>
{
props.image ?
<img src={props.image} height="50" width="50" className="Person-image"
alt="avatar"/>
: <svg height="50" width="50" className="Person-image">
<rect fill="cornflowerblue" x="0" y="0" height="50" width="50"/>
<text
fill="#ffffff"
fontSize="20"
textAnchor="middle"
x="25"
y="30">{props.first_char.toUpperCase()}</text>
</svg>
}
</div>
</Col>
</Row>
</Container>
</article>
);
});
class PersonList extends Component {
state = {
persons: [],
show: false
};
componentDidMount() {
axios.get('')
.then(response => {
const result = response.data.data.slice(0, 5);
this.setState({persons: result});
});
}
personSelectedHandler = (id) => {
this.showModal();
};
showModal = () => {
this.setState({ show: true });
};
hideModal = () => {
this.setState({ show: false });
};
render() {
const persons = this.state.persons.map(person => {
let avatar;
if (person.picture_id != null) {
avatar = person.picture_id.pictures["128"];
}
return <ListGroup>
<ListGroup.Item>
<Person
key={person.id}
name={person.name}
company={person.org_id.name}
first_char={person.first_char}
image={avatar}
clicked={() => this.personSelectedHandler(person.id)}
/>
</ListGroup.Item>
</ListGroup>
});
return (
<div className="Wrapper">
<Modal show = {this.state.show} handleClose = {this.hideModal}/>
<Header/>
<div className="Breadcrumb">
<h4 className="Breadcrumb-text"><b>People's List</b></h4>
<hr/>
</div>
{persons}
</div>
);
}
}
export default PersonList;
类PersonList扩展组件{
状态={
人员:[],
节目:假
};
componentDidMount(){
axios.get(“”)
。然后(响应=>{
const result=response.data.data.slice(0,5);
this.setState({persons:result});
});
}
personSelectedHandler=(id)=>{
这是showModal();
};
showModal=()=>{
this.setState({show:true});
};
hideModal=()=>{
this.setState({show:false});
};
render(){
const persons=this.state.persons.map(person=>{
让阿凡达;
if(person.picture_id!=null){
阿凡达=person.picture_id.pictures[“128”];
}
返回
this.personSelectedHandler(person.id)}
/>
});
返回(
人民名单
{个人}
);
}
}
导出默认个人列表;
如果你最终需要<代码> ID>代码>上下文,你可能想考虑使用父母的状态来实现你所追求的,如果你真的想要避免重新渲染。
您还可以将Person
转换为(纯)类组件,并在该组件内处理回调
最后,如果推到了紧要关头,您必须使用这个内嵌箭头函数,您可以覆盖React.memo
的比较函数,这大致类似于为类组件定义组件shouldUpdate
也许还有另一种我不知道的方法可以让这一切顺利进行,但希望这能帮助您理解这个问题,并探索其他解决方案。这里还有一些想法和讨论:如果您使用hook,您可以将
useCallback()
方法与Recat.memo
一起使用。
在您的componenet中:
const callBack = useCallback(() => this.personSelectedHandler(person.id),[person.id]);
useCallback((person.id)=>personSelectedHandler(person.id),[person.id])只要person.id
相同,code>始终返回相同的函数实例。
然后:
使用shouldComponentUpdate生命周期来防止重新渲染感谢您的回答。我将无状态函数组件更改为React.component,并在其中使用了shouldComponentUpdate。我不能让它与其他选项一起工作。没问题,这是一个需要处理的恼人的用例。如果您想继续使用带有React.memo
的功能组件,我澄清了覆盖React.memo的比较函数的答案。它应该与定义componentdiddupdate
大致相同(尽管如果组件不应重新渲染,它应该返回相反的值;true
)。不过,我从未在这个特殊的案例中使用过它,也不确定是否有任何我不知道的陷阱。
const callBack = useCallback(() => this.personSelectedHandler(person.id),[person.id]);
<Person
...
clicked={callBack}
/>