在父母的状态改变之后,反应更新孩子的道具

时间:2018-05-02 01:44:45

标签: reactjs react-props

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

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

问题是在回调触发之前设置了道具。我在想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;

2 个答案:

答案 0 :(得分:1)

有更多可能的选择如何实现这个结果

条件渲染

只有当道具改变了那个menas

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

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

未定义/假道具的Guard组件

<强> 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
  }
}

答案 1 :(得分:1)

新的Context API是解决此类问题的方法。我想了解一下,但我想到的是editorState作为道具获得Sidebar

  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>
      ); 
  }
}
现在看着它看起来非常简单,这意味着我已经学到了很多东西!如果我能在这里做任何改进,请告诉我。