在 parent 的状态改变后反应更新 child 的道具

React update child's props after parent's state change

我正在尝试将 Draft.js 的编辑器状态从编辑器组件传递到我自己的 Sidebar 组件。

使用最顶层的组件 Notes 我使用回调从 CustomEditor 获取编辑器状态并将其设置为 Notes 状态。然后我将该状态作为道具传递给 Sidebar

问题是 prop 是在回调触发之前设置的。我在想 setTimeout 但这似乎很粗糙。我知道 UNSAFE_componentWillReceiveProps() 但文档不推荐它。这个用例有反应吗?

export class Notes extends Component {
  constructor(props) {
    super(props);
    this.getEditorState = this.getEditorState.bind(this)
    this.state = {
      editorState: "the placeholder data Sidebar should not have as a prop"
    };
  }

  getEditorState(state) {
    console.log(state)
    this.setState({editorState: state})
  }

  render() {
    return (
      <section id="Notes">
        <div id="editor-holder">
          <Sidebar currentEditorState={this.state.editorState}/>
          <div id="Editor">
            <FileHeader />
            <CustomEditor getState={this.getEditorState}/>
          </div>
        </div>
      </section>
    );
  }

}

export default Notes;

好吧,还有更多可能的选择来实现这个结果

条件渲染

只有当道具改变了 menas

时,您才能渲染 <Sidebar>
constructor(props)
  super(props)
  this.state = {
    editorState: false
  }
}

render() {
 ... {this.state.editorState && <Sidebar currentEditorState={this.state.editorState}/>}
}

undefined/false 道具的保护组件

Sidebar.js

render() {
  if(!this.props.currentEditorState) return null // this will force React to render nothing

  return ( ... )
}

使用 getDerivedState 将道具转换为状态

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

Sidebar.js

static getDerivedStateFromProps({ currentEditorState }, prevState) {
  if(currentEditorState !== false {
   return { currentEditorState }
  } else {
   return {}
  }
}

render() {
  (.... something bound to this.state.currentEditorState)
}

使用上下文(遗留上下文)

class Notes extends React.Component {
 getEditorState(state) {
    console.log(state)
    this.setState({editorState: state})
  }

  getChildContext() {
    return {
      editorState: this.state.editorState
    }
  }

  childContextTypes = {
    editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
  }
}

Sidebar.js

class Sidebar {
  static contextTypes = {
    editorState: PropTypes.oneOfType([PropTypes.obj, PropTypes.bool])
  }

  render() {
    ... this.context.editorState
  }
}

新的 Context API 是解决此类问题的方法。花了一点时间来理解它,但我想出的是 editorStateSidebar 作为道具。

  export const NoteContext = React.createContext("placeholderEditorState");

  export class Notes extends Component {
    constructor(props) {
      super(props);
      this.getEditorState = this.getEditorState.bind(this)
      this.getFolderData = this.getFolderData.bind(this)
      this.state = {
        editorState: null,
        folderData: null
      };
    }

    getEditorState(state) {
      this.setState({editorState: state});
    }

    getFolderData(data) {
      this.setState({folderData : data})
    }

    render() {
      return (
        <section id="Notes">
          <TopBar />
          <div id="editor-holder">

            <NoteContext.Provider value={{editorState: this.state.editorState}} >
              <NoteContext.Consumer>
                {(context)=>{ return (
                  <Sidebar currentEditorState={context.editorState} getFolderData={this.getFolderData}/>
                )}}
              </NoteContext.Consumer>
            </NoteContext.Provider>

              <div id="Editor">

                <NoteContext.Provider value={{folderData: this.state.folderData}} >
                  <FileHeader />
                </NoteContext.Provider>

                <CustomEditor getState={this.getEditorState}/>
              </div>

          </div>
        </section>
      ); 
  }
}

现在看来很简单,也算是学到了很多东西!让我知道我是否可以在这里改进任何内容。