我有两个无状态组件和一个有状态组件。在我的有状态组件中,我有一个人员列表,当我单击其中的一个时,它会打开一个模式。我基本上将模态的状态存储在有状态组件中,并将值作为道具发送给模态。因此,只要打开模型并重新渲染所有内容,它就会随时更改状态。
如何在更改状态后阻止重新渲染无状态类?
我在无状态组件中尝试过备忘录,但是没有运气
模块组件
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 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;
答案 0 :(得分:1)
onRequest
这将在每次重新渲染父函数时为<Person
...
clicked={() => this.personSelectedHandler(person.id)}
/>
定义一个新的函数引用。这将导致props.clicked
的道具在每次渲染时都发生更改,从而导致Person
也重新渲染。
由于您当前不在Person
中使用id
,因此可以省略参数并保持函数引用不变:
personSelectedHandler
如果您最终需要使用clicked={this.personSelectedHandler}
上下文,那么您可能想考虑使用父母的状态来实现自己所追求的目标,如果您真的想避免的话重新渲染。
您还可以将id
转换为(纯)类组件,并从该组件内部处理回调。
最后,如果要推一下推,而您绝对必须使用此嵌入式箭头功能,则可以覆盖Person
的比较功能,这与为类组件定义React.memo
类似。 From the docs:
componentShouldUpdate
我可能不知道有另一种方法可以完成这项工作,但是希望这可以帮助您了解问题,以探索替代解决方案。这里也有一些想法和讨论:Why shouldn't JSX props use arrow functions or bind?
答案 1 :(得分:1)
如果使用钩子,则可以将v-model
与useCallback()
一起使用。
在您的componenet中:
Recat.memo
只要const callBack = useCallback(() => this.personSelectedHandler(person.id),[person.id]);
相同, useCallback((person.id) => personSelectedHandler(person.id),[person.id]);
总是返回相同的函数实例。
然后:
person.id