如何避免在React中重新渲染?

问题描述

我正在制作一个带有文本编辑器的简单手风琴。

如果单击扩展文本,则将打开文本编辑器;如果在编辑器中输入一些文本,然后单击收缩,则手风琴将关闭

再次单击我们进行更改的手风琴的展开文本,则其中已经输入的文本会丢失。

我了解到,每次我们单击扩展文本时,都会重新渲染。还有这段代码

<Text>  {toggleValue === index && item.content && <EditorContainer />} </Text>

检查单击的项目,然后将其打开,以便在此处进行重新渲染,因此我丢失了输入的文本。

完整的工作示例:

https://codesandbox.io/s/react-accordion-forked-dcqbo

尽管单击了文本“展开/收缩”,您能否请我保留在文本编辑器中输入的值?

解决方法

将编辑器的状态放入持久的父组件中。由于NormalAccordion包含所有编辑器,并且您只希望持久状态为一个编辑器,因此请使用另一个组件,这样在卸载该编辑器时状态不会丢失,然后将其传递给编辑器使用:

const OuterEditorContainer = ({ toggleValue,setToggleValue,item,index }) => {
  const [editorState,setEditorState] = useState(EditorState.createEmpty());

  const toggleHandler = (index) => {
    index === toggleValue ? setToggleValue(-1) : setToggleValue(index);
  };
  return (
    <Accordion>
      <Heading>
        <div
          style={{ padding: "10px",cursor: "pointer" }}
          className="heading"
          onClick={() => toggleHandler(index)}
        >
          {toggleValue !== index ? `Expand` : `Shrink`}
        </div>
      </Heading>
      <Text>
        {toggleValue === index && item.content && (
          <EditorContainer {...{ editorState,setEditorState }} />
        )}
      </Text>
    </Accordion>
  );
};
const NormalAccordion = () => {
  const [toggleValue,setToggleValue] = useState(-1);
  return (
    <div className="wrapper">
      {accordionData.map((item,index) => (
        <OuterEditorContainer
          {...{ toggleValue,index }}
        />
      ))}
    </div>
  );
};
// text_editor.js
export default ({ editorState,setEditorState }) => (
  <div className="editor">
    <Editor
      editorState={editorState}
      onEditorStateChange={setEditorState}
      toolbar={{
        inline: { inDropdown: true },list: { inDropdown: true },textAlign: { inDropdown: true },link: { inDropdown: true },history: { inDropdown: true }
      }}
    />
  </div>
);

您还可以将状态放入text_editor本身,并始终渲染该容器,但仅有条件地渲染<Editor

,

您需要保存输入的文本,并将其作为道具从父组件传递到EditorContainer。

现在,每次渲染时(例如,当我们单击“展开”时) 好像您设置了一个空状态。

类似的东西:

EditorContainer

  editorState: this.props.editorState || EditorState.createEmpty()

  onEditorStateChange = (editorState) => {
    // console.log(editorState)
    this.props.setEditorState(editorState);
  };

手风琴中:

{toggleValue === index && 
 item.content && 
<EditorContainer 
editorState={this.state.editorState[index]} 
setEditorState={newText => this.setState({...this.state,newText}) />}

没有尝试执行它,但是我认为这是实现它的方法。 附言:类组件几乎不再使用。尝试使用功能组件并了解useState钩子,我认为它看起来更干净