我很难确定我的组件层次结构是否真的需要getDerivedStateFromProps
,如果需要它的情况真的像文档所说的那样罕见。这可能是对React/Redux设计的根本误解。
class AttributeList extends React.Component {
constructor(props){
super(props)
this.state = {
attributes: props.attributes,
newAttributes: []
}
}
addNewAttribute = () => {
// add new empty attribute to newAttributes state
}
onKeyChange = () => {
// update appropriate attribute key
}
onValueChange = () => {
// update appropriate attribute value
}
saveAttributes = () => {
// save the, API call
}
render = () => {
this.state.attributes.map((pair) => {
<Attribute
//pass data + functions, functional component />
})
this.state.newAttributes.map((pair) => {
<Attribute
//pass data + functions, functional component />
})
}
static getDerivedStateFromProps(){
// ?? do comparisons here to choose to remove or keep certain newAttributes? or just ignore result of save and keep interface as-is, just show error message if saving failed.
}
}
我有一个父组件AttributeList
,它呈现了一堆Attributes
,它们本质上是键值对。CCD_ 4接收文档的属性列表作为道具。但是,属性可以编辑,因此它会用this.props.attributes
初始化其状态(this.state.attributes
(。通常键是不可变的,但如果用户向列表中添加新属性,他可以编辑键和值。在任何时候,用户都可以保存所有属性。保存新属性时,我也希望禁用为它们编辑关键帧。这就是困境。
选项一是保存文档并希望它有效,然后清除新的属性列表并将所有属性标记为已保存(禁用键输入(。我认为这将是一个"完全不受控制"的解决方案,一旦状态初始化,组件就会自己处理所有事情。但是,如果保存失败怎么办?我不想向用户显示错误的状态。
所以我想做选项二。保存后,获取文档,文档将加载属性列表并重新呈现组件。然而,我需要去掉我的新属性,因为它们现在是attributes
道具的一部分。我现在想验证一下,新属性实际上是attributes
道具的一部分。这似乎会发生在getDerivedStateFromProps
中,在每个渲染周期中,我都会检查attributes
道具中是否已经存在任何新的属性键,如果存在,则将它们从"新"列表中删除,并返回该状态。
但现在真的是使用getDerivedStateFromProps
的合适时机吗?在我看来,对于任何用户正在"编辑"的页面,如果您调用API来保存它,如果您想根据保存的数据("真相"(进行渲染,那么我需要使用getDerivedStateFromProps
。或者,从设计的角度来看,最好显示类似于"数据未成功保存"的消息,并保持原样,以防止任何数据丢失。我真的不确定。
我不知道getDerivedStateFromProps
是如何进入状态的,因为没有理由需要将道具复制到状态中,是吗?当旧属性值更改时,您可以将其保存到redux存储中,当新属性属性更改时,可以更新本地状态(或将它们保存到存储的不同部分,或以其他方式区分它们(。更新规则可以在更新处理程序中强制执行,也可以在保存时合并期间强制执行。
// dispatch redux action to update store
onOldValueChange = () => {}
// this.setState to update new value
onNewKeyChange = () => {}
onNewValueChange = () => {}
render = () => {
this.props.attributes.map((pair) => {
<Attribute
//pass data + onOldValueChange, functional component />
})
this.state.newAttributes.map((pair) => {
<NewAttribute
//pass data + functions, functional component />
})
}