我想了解react组件构造函数的行为。假设我有三个组件-PageComponent,ListComponent和ItemComponent。我的伪代码结构是:
PageComponent(从redux获取数据,获取数据)
ListComponent(获取数据作为道具,在循环中(地图)呈现ItemComponents的列表)
ItemComponent(获取道具数据,渲染道具,操纵数据)
逻辑: -当ItemComponent中的数据发生更改时,更改将存储在REDUX中,并且此更改导致列表重新呈现。
用例1:
-PageComponent呈现ListComponent,而ListComponent呈现ItemComponets的列表
-在REDUX listItem数据更改时,将更新PageComponent,将更新ListComponent,并调用ItemComponent CONSTRUCTOR(重置其本地状态)
用例2:
-PageComponent仅呈现ItemComponents的LIST(使用映射循环)。
-当REDUX listItem数据更改时,PageComponent会更新,而不会调用ItemComponent CONSTRUCTOR(组件“仅”更新)(并且不会重置其本地状态)
为什么这些示例中的行为不同?
源代码: PageComponent:
import React from 'react'
...
class UsersPage extends React.Component {
constructor(props) {
super(props)
props.actions.getUsers();
}
render() {
const {users} = this.props
return (
<Main>
{/* // NO ITEM CONSTRUCTOR IS CALLED
users.data.items.map((item, index) => {
return <ListItemComponent
data={item}
itemMethods={{
getItem: (data) => this.props.actions.getUser(data),
onEdit: (data) => this.props.actions.updateUser(data),
onDelete: (data) => this.props.actions.deleteUser(data),
validation: (data) => validateInput(this.props.strings, data)
}}
key={index}
/>
})*/
}
{ // ITEM CONSTRUCTOR IS CALLED
<ListComponent
loading={users.isFetching}
data={users.data}
methods={{
getItem: (data) => this.props.actions.getUser(data),
onEdit: (data) => this.props.actions.updateUser(data),
onDelete: (data) => this.props.actions.deleteUser(data),
validation: (data) => validateInput(this.props.strings, data)
}}
/>}
</Main>
);
}
}
UsersPage.propTypes = {
users: PropTypes.object.isRequired,
strings: PropTypes.object.isRequired,
}
function mapStateToProps(state) {
return {
users: state.users,
strings: state.strings.data || {},
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getUsers,
getUser,
addUser,
updateUser,
deleteUser,
}, dispatch)
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(withAlert(UsersPage));
ListComponent:
import React from 'react'
...
class ListComponent extends React.Component {
getList() {
return <div className="list-outer">
<Row>
{
items.map((item, index) => {
return <ListItemComponent
data={item}
itemMethods={methods}
key={index}
/>
})
}
</Row>
</div>
}
render() {
const {loading} = this.props
return (
<div className="list-wrapper">
{
loading ? <Spinner visible={true}/>
:
this.getList()
}
</div>
)
}
}
ListComponent.propTypes = {
loading: PropTypes.bool.isRequired,
data: PropTypes.object.isRequired,
methods: PropTypes.object.isRequired,
}
export default ListComponent
ListItemComponent:
import React from 'react'
...
class ListItemComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
editMode: false,
}
}
toggleEditMode(){
const editMode = this.state.editMode
this.setState({editMode: !editMode})
}
onEdit(id) {
const itemMethods = this.props.itemMethods
this.toggleEditMode()
itemMethods.getItem({id: id})
}
onDelete(item) {
//...
}
getFields(rowData, index) {
return <div key={index}>
{
rowData.map((itm, idx) => {
return <div key={idx}>{itm.label}: {itm.value}</div>
})
}
</div>
}
render() {
const editMode = this.state.editMode
const {data, itemMethods, strings} = this.props
return (
editMode ?
<Form
id={data.id}
onSubmit={(data) => itemMethods.onEdit(data)}
validation={(data) => itemMethods.validation(data)}
onCloseForm={() => this.toggleEditMode()}
/>
:
<Col xs={12}>
<div>
<div
{this.getFields(data)}
</div>
<div className="controls">
<button
className="btn btn-theme inverse danger"
onClick={() => this.onDelete(data)}
>{strings.delete}</button>
<button
onClick={() => this.onEdit(data.id)}
className="btn btn-theme" type="button"
>
{strings.edit}
</button>
</div>
</div>
</Col>
)
}
}
ListItemComponent .propTypes = {
strings: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
itemMethods: PropTypes.object.isRequired,
}
function mapStateToProps(state) {
return {
strings: state.strings.data || {}
};
}
export default connect(
mapStateToProps,
null,
)(ListItemComponent )
答案 0 :(得分:0)
确保每个ItemComponent都有一个key
道具集。当React渲染项目列表时,它需要知道如何识别每个元素,React则由您自己决定。如果省略key
道具,React将在每次重新渲染时销毁并重新创建列表,这意味着调用组件构造函数。
如果您提供所使用的确切代码,我们可以更好地指出您问题的出处。
您可以了解有关列表和键here的更多信息。
答案 1 :(得分:0)
已解决
这是由ListComponent和作为渲染条件中的条件放置的加载道具引起的。编辑项目时,道具加载设置为true,微调器变为可见,并且它是ListComponent中的唯一元素,因此列表项已卸载