【问题标题】:When to really use getDerivedStateFromProps?何时真正使用 getDerivedStateFromProps?
【发布时间】:2018-12-10 04:43:12
【问题描述】:

我无法确定我的组件层次结构是否真的需要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,它们本质上是键值对。 AttributeList 接收文档的属性列表作为道具。但是,可以编辑属性,因此它使用this.props.attributes 初始化其状态(this.state.attributes)。通常键是不可变的,但如果用户向列表中添加新属性,他可以同时编辑键和值。在任何时候,用户都可以保存所有属性。保存新属性后,我也想禁用编辑它们的键。这是两难的。

选项一是保存文档并希望它能正常工作,然后清除新属性列表并将所有属性标记为已保存(禁用键输入)。我认为这将是“完全不受控制”的解决方案,一旦状态被初始化,组件就会自行处理所有事情。但是,如果保存失败怎么办?我不想向用户显示不正确的状态。

所以我想做选项二。保存后,获取文档,这将加载属性列表并重新渲染组件。但是我需要摆脱我的新属性,因为它们现在是 attributes 属性的一部分。我想现在验证新属性实际上是 attributes 道具的一部分。这似乎会发生在getDerivedStateFromProps 中,我会在每个渲染周期检查attributes 道具中是否已经存在任何新的属性键,如果存在,则将它们从“新”列表中删除,并返回该状态。

但这真的是使用getDerivedStateFromProps 的正确时机吗?在我看来,对于用户正在“编辑”某些内容的任何页面,如果您想根据保存的数据(“真相”)进行渲染,那么我需要使用 @987654335 @。或者从设计的角度来看,最好显示类似于“数据未成功保存”的消息并保持状态不变,以防止任何数据丢失。老实说,我不确定。

【问题讨论】:

  • 如果您想了解何时使用 getDerivedStateFromProps 的建议,我建议您阅读官方 React 文档 - reactjs.org/blog/2018/06/07/… 如果您计划在成功的数据保存更改上同步 props 的状态,那么文档说这是一种反模式。如果可以的话,我会建议做一个完全受控的组件。如果您无法重新设计,那么是的,您可以使用 getDerivedStateFromProps 来实现您想要的,如果数据成功保存,您可以从 props 更新您的本地状态。恕我直言,应该是您唯一的最后选择。

标签: javascript reactjs redux getderivedstatefromprops


【解决方案1】:

我不明白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 />
  })
}

【讨论】:

  • 但是当一个 newAttribute 被保存时呢?获取刚刚更新的文档是惯用的吗?如果是这样,attributes prop 现在可能包含刚刚保存的 newAttributes 之一,因此我应该从状态中删除该 newAttribute。
  • 是的,一旦保存新属性,您就会从状态中删除它们。
  • 那会是什么样子?保存时,调度操作以再次获取文档。获取文档,新的属性prop传下来,然后如果新的属性和旧的属性不同(在componentDidUpdate中),根据需要setState?
  • hmm.. 我想我会倾向于做一个乐观的更新,即用状态值更新存储,然后保存到服务器。根据您的 api,您可以保存到商店的内容或状态的内容,因此当您清除状态时,将归结为适用于您的应用程序的时间以及您将如何处理保存失败。 state 或 store 中的请求跟踪可用于不呈现 state 属性,而它们同时存在于 state 和 store (props) 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-11
相关资源
最近更新 更多