Реакция обновления реквизитов ребенка после изменения состояния родителя - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь передать состояние редактора Draft.js из компонента editor в мой собственный компонент 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 голосов
/ 07 мая 2018

Новый API-интерфейс Context является решением этой проблемы. Потребовалось немного, чтобы обдумать это, но то, что я придумал, получает 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>
      ); 
  }
}

Глядя на это сейчас, это кажется очень простым, это означает, что я многому научился! Дайте мне знать, если я смогу что-то улучшить здесь.

0 голосов
/ 02 мая 2018

Ну, есть еще возможные варианты, как этого добиться

Условный рендеринг

Вы можете визуализировать <Sidebar> только тогда, когда реквизит изменил это меню

constructor(props)
  super(props)
  this.state = {
    editorState: false
  }
}

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

Компонент охраны для неопределенного / ложного реквизита

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
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...