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

How to avoid re-render in React?

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

如果我们点击展开文本,那么文本编辑器就会打开,如果我们在编辑器中输入一些文本,然后点击收缩,那么手风琴就会关闭。

同样,如果单击我们进行更改的手风琴的展开文本,则已经输入的文本在其中丢失。

我可以理解每次点击展开文本时都会重新渲染。还有这段代码,

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

检查点击的项目然后它被打开,所以重新渲染发生在这里,因此我丢失了输入的文本。

完整的工作示例:

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

尽管点击了文本,您能否帮我保留在文本编辑器中输入的值 Expand/Shrink?

将编辑器的状态放入持久化父组件中。由于 NormalAccordion 包含所有编辑器,并且您只需要 one 编辑器保持状态,请使用另一个组件,以便在卸载编辑器时状态不会丢失,然后通过下来供编辑使用:

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, setToggleValue, item, 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.

您需要保存输入的文本并将其作为 props 从父组件传递给 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}) />}

没有尝试执行它,但我认为这是实现它的方式。 Ps: Class 组件几乎不用了。尝试使用函数组件并了解 useState hook,在我看来看起来更干净