【问题标题】:How to avoid re-render in React?如何避免在 React 中重新渲染?
【发布时间】:2020-12-21 04:08:54
【问题描述】:

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

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

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

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

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

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

完整的工作示例:

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

尽管点击文本展开/收缩,您能否帮我保留在文本编辑器中输入的值?

【问题讨论】:

    标签: javascript reactjs editor accordion


    【解决方案1】:

    将编辑器的状态放入一个持久的父组件中。由于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, 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 本身,并始终渲染该容器,但仅有条件地渲染&lt;Editor

    【讨论】:

    • 感谢您的回答。您能否通过在问题中分叉我的来提供工作沙箱?
    • 答案的变化确实是你所需要的,但如果你也需要一个链接:codesandbox.io/s/react-accordion-forked-mi7s0?file=/src/…
    • 再次感谢您提供链接。但是在这里,如果我在任何编辑器中输入文本并且如果我关闭该手风琴并且如果我打开任何其他手风琴,那么之前输入的文本就会出现在其他无关的手风琴里面..请您检查一下吗?
    • 编辑器中输入的文本仅与特定的手风琴有关。现在任何文本编辑器中的更改都会反映在所有其他文本编辑器中。
    • 哦,你有一个.map,这样他们就可以共享相同的状态了。为每个编辑器使用不同的容器,并将每个编辑器的持久状态放入其中。
    【解决方案2】:

    您需要保存输入的文本并将其作为 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:类组件几乎不用了。尝试使用函数组件,学习useState钩子,在我看来看起来干净多了

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      相关资源
      最近更新 更多