我有两个无状态组件和一个有状态组件。在我的有状态组件中,我有一个人员列表,当我点击其中一个时,它会打开一个模态。我基本上将模态的状态存储在有状态组件中,并将值作为道具发送到模态。因此,它会在打开模型并重新渲染所有内容时随时更改状态。
在更改状态后,如何防止无状态类重新呈现?
我在无状态组件中尝试过备忘录,但没有运气
模态组件
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;
<Person
...
clicked={() => this.personSelectedHandler(person.id)}
/>
这将在每次重新渲染父函数时为props.clicked
定义一个新的函数引用。这将导致Person
的道具在每次渲染时被更改,导致Person
也重新渲染。
既然你目前没有在id
中使用personSelectedHandler
,你可以省略参数并保持函数引用不变:
clicked={this.personSelectedHandler}
如果你最终需要id
上下文,你可能想要考虑使用父母的状态来实现你所追求的目标,如果你真的想避免重新渲染。
您还可以将Person
转换为(纯)类组件,并处理该组件内的回调。
最后,如果push推进并且你绝对必须使用这个内联箭头函数,你可以覆盖React.memo
的比较函数,这大致类似于为类组件定义componentShouldUpdate
。 From the docs:
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
export default React.memo(MyComponent, areEqual);
可能还有另一种方法我不知道如何使这项工作,但希望这有助于您了解探索替代解决方案的问题。这里也有一些想法和讨论:Why shouldn't JSX props use arrow functions or bind?