Я делаю простой аккордеон с текстовым редактором внутри.

Если мы щелкнем «Развернуть текст», откроется текстовый редактор, а если мы введем какой-то текст внутри редактора и нажмем «сжать», то аккордеон закроется.

Опять же, если щелкнуть развернутый текст аккордеона, в котором мы внесли изменения, то уже введенный текст внутри него отсутствует.

Я понимаю, что этот рендеринг происходит каждый раз, когда мы нажимаем на развернутый текст. Также этот код,

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

Проверьте элемент, на который щелкнули, затем он открывается, поэтому здесь происходит повторный рендеринг, и поэтому я теряю введенный текст.

Полный рабочий пример:

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

Не могли бы вы помочь мне сохранить значение, введенное в текстовом редакторе, несмотря на щелчки по тексту Expand / Shrink?

0
Undefined 2 Сен 2020 в 05:39

2 ответа

Лучший ответ

Поместите состояние редактора в постоянный родительский компонент. Поскольку 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 и всегда отображать этот контейнер, но только условно отображать <Editor.

1
CertainPerformance 2 Сен 2020 в 03:10

Вам необходимо сохранить введенный текст и передать его в качестве реквизита из родительского компонента в 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, выглядит так много чище на мой взгляд

1
Pedro Silveira 2 Сен 2020 в 03:00