简体   繁体   中英

ReactJS - Child unable to access parent state after update

I have an input field in a child component that is prefilled from the value of a parent's state.

Since I pass the current value to the child as a prop and a function to update this value in the parent, it seems that whenever I update the parent from the passed function, my child is suddenly not able to access the parent state.

My parent's state:

  const [blockList,setBlockList] = useState({
    "0":{
      type:"loading",
      content:{
        'title':"placeholder_title",
        'description':"placeholder_description"
      }
    },
    "1":{
      type:"description",
      content:{
        'title':"placeholder_title",
        'description':"placeholder_description"
      }
    },
    "2":{
      type:"skills_and_requirements",
      content:{
        'title':"",
        'description':""
      }
    },
  })

The function passed to the child:

const _getBlockContent = (
  currentBlockKey, 
  contentKey, 
  returnedContent
) => {
  setBlockList(blockList[currentBlockKey].content[contentKey] = returnedContent)
}

What I pass to the child:

  return (    
      <Child
        currentBlock={blockList[selectedBlock]} // (i.e. selectedBlock = '1')
        _getBlockContent={_getBlockContent}
        currentBlockKey={selectedBlock} // (i.e. selectedBlock = '1')
      /> )

Now, whenever I save the input in the child and use the function _getBlockContent to update the state of my parent, this causes my Child to break.

TypeError: props.currentBlock.content is undefined

Full child (draftJS) :

const EditorPanel = (props) => {

  //receives the block from the parent. The block type will define the advice and other static elements of the pannel. The block content will define what to include in the input and editor fields.
  //This function should be passed to the editor and update the block content. 
  const _getEditorContent = (contentKey, returnedContent) => {
    console.log("contentKey is: %s", contentKey);
    console.log("returnedContent is: %s", returnedContent);
    props._getBlockContent(props.currentBlockKey,contentKey, returnedContent)
  }

  return(
    <div className="edit_panel">
      <div className="edit_panel_container">
        <h2>Description</h2>
        <h3>Title</h3>
        <MyEditor 
          contentKey={'title'}
          contentValue={props.currentBlock.content['title']}
          _getEditorContent={_getEditorContent}
        />
        <p>Title of this section should be eiusmod  dolor sit amet, consectetur.</p>
        <h3>Description</h3>
        <MyEditor 
          contentKey={'description'}
          contentValue={props.currentBlock.content['description']}
          _getEditorContent={_getEditorContent}
        />

        <p
        >Title of this section should be eiusmod  dolor sit amet, consectetur.</p>
        <p>Title of this section should be eiusmod  dolor sit amet, consectetur.</p>
      </div>
    </div>
  );
};


class MyEditor extends React.Component {
  constructor(props) {
    super(props);
    //this.state = {editorState: EditorState.createEmpty()};
    this.state = {editorState: EditorState.createWithContent(
      stateFromHTML(props.contentValue)
    )};
    this.onChange = editorState => {
      this.setState({editorState});
      //this.returnEditorHTML()
    }
    this.handleKeyCommand = this.handleKeyCommand.bind(this);
    this.focus = () => this.editor.focus();
    this.returnEditorHTML = editorState => {
      const content = stateToHTML(this.state.editorState.getCurrentContent());
      props._getEditorContent(props.contentKey,content);
    };
  }



  handleKeyCommand(command, editorState) {
    const newState = RichUtils.handleKeyCommand(editorState, command);

    if (newState) {
      this.onChange(newState);
      return 'handled';
    }

    return 'not-handled';
  }

  _onBoldClick() {
    this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
  }

  _onItalicClick() {
    this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'ITALIC'));
  }

  _onUnderlineClick() {
    this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'UNDERLINE'));
  }

  render() {
    return (
      <div>
        <div className="draft_input">
          <Editor 
            editorState={this.state.editorState}
            handleKeyCommand={this.handleKeyCommand}
            onChange={this.onChange} 
          />
        </div>
        <button onClick={this._onItalicClick.bind(this)}>I<i className="fas fa-bold"></i></button>
        <button onClick={this._onBoldClick.bind(this)}>B</button>
        <button onClick={this._onUnderlineClick.bind(this)}>U</button>
        <button onClick={this.returnEditorHTML}>save</button>
        <div></div>
      </div>
    );
  }
}

In your _getBlockContent function, you replace the entire state with returnedContent , whereas instead you need to replace just the key you want to update:

const _getBlockContent = (
  currentBlockKey, 
  contentKey, 
  returnedContent
) => {
  const newBlockList = {
    ...blockList,
    [currentBlockKey]: {
        ...blockList[currentBlockKey],
        [contentKey]: returnedContent,
    }
  };
  setBlockList(newBlockList);
}

Since your _getBlockContent actually updates state, you should consider renaming it to something like setBlockContent or onBlockContentChanged to make it more clear than it is performing a write rather than a read

I see something.

Going by your naming, _getBlockContent(..) is meant for retrieving the state. Please note, setBlockList(..) is not meant for reading the state, it is only used for updating the state. For reading the state, you can directly use blockList in your function component _getBlockContent(..) like below.

    return blockList[currentBlockKey].content[contentKey];

Besides that, to actively reproduce your error on my end, can you share a github link or something containing all the components in your logic (including < Editor > etc)?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM