javascript - Draft JS editor does not update it's content when its value changed by parent component? - Stack Overflow

I've a simple use case: There's a DraftEditor ponent which takes value as its prop and create

I've a simple use case: There's a DraftEditor ponent which takes value as its prop and create a editor state based on value (empty or with content). It possible that the value gets changed by the parent and when it does, I expect the Draft Editor to update it's content as well. Here's my DraftEditor ponent.

import React, { useState } from "react";
import { Editor, EditorState, convertFromRaw } from "draft-js";

export default ({ value }) => {
  const initialState = value
    ? EditorState.createWithContent(convertFromRaw(JSON.parse(value)))
    : EditorState.createEmpty();
  const [editorState, setEditorState] = useState(initialState);

  return <Editor editorState={editorState} onChange={setEditorState} />;
};

The problem: When value is updated by the parent ponent, the contents of Editor is not getting updated. Instead, it just shows the content it was initialized with. The workaround I found is to manually call setEditorState when the value changes, but I feel this step is unnecessary as when the ponent re-renders I expect the editor to recalculate it's internal state as well? May be I am missing something here?

Any idea why the Editor is not updating it's internal state?

Here's a code sandbox: ;hidenavigation=1&theme=dark

I've a simple use case: There's a DraftEditor ponent which takes value as its prop and create a editor state based on value (empty or with content). It possible that the value gets changed by the parent and when it does, I expect the Draft Editor to update it's content as well. Here's my DraftEditor ponent.

import React, { useState } from "react";
import { Editor, EditorState, convertFromRaw } from "draft-js";

export default ({ value }) => {
  const initialState = value
    ? EditorState.createWithContent(convertFromRaw(JSON.parse(value)))
    : EditorState.createEmpty();
  const [editorState, setEditorState] = useState(initialState);

  return <Editor editorState={editorState} onChange={setEditorState} />;
};

The problem: When value is updated by the parent ponent, the contents of Editor is not getting updated. Instead, it just shows the content it was initialized with. The workaround I found is to manually call setEditorState when the value changes, but I feel this step is unnecessary as when the ponent re-renders I expect the editor to recalculate it's internal state as well? May be I am missing something here?

Any idea why the Editor is not updating it's internal state?

Here's a code sandbox: https://codesandbox.io/s/xenodochial-sanderson-i95vd?fontsize=14&hidenavigation=1&theme=dark

Share Improve this question asked Jan 20, 2020 at 23:18 VeeraVeera 33.2k36 gold badges100 silver badges138 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

The basic problem is

const [editorState, setEditorState] = useState(initialState);

uses it's parameter initialState only once (on initial run-through), no matter how many times initialState changes.

When using useState() and there is a prop (or other) dependency, pair it with a useEffect() to make things reactive.

This may seem a bit backwards, but a lot of (most of) the hooks are about keeping things the same when the Function ponent is re-run. So useState() only updates editorState via setEditorState, after the initial call.

import React, { useState, useEffect } from "react";
import { Editor, EditorState, convertFromRaw } from "draft-js";

export default ({ value }) => {

  const [editorState, setEditorState] = useState();

  useEffect(() => {
    const state = value
      ? EditorState.createWithContent(convertFromRaw(JSON.parse(value)))
      : EditorState.createEmpty();
    setEditorState(state);
  }, [value]); // add 'value' to the dependency list to recalculate state when value changes.

  return <Editor editorState={editorState} onChange={setEditorState} />;
};

In the code above, editorState will be null on initial ponent call. If this is a problem for the Editor ponent, you can externalize the state calculation in a function and call it for useState() and within useEffect().

import React, { useState, useEffect } from "react";
import { Editor, EditorState, convertFromRaw } from "draft-js";

export default ({ value }) => {

  const [editorState, setEditorState] = useState(calcState(value));

  useEffect(() => {
    setEditorState(calcState(value));
  }, [value]); // add 'value' to the dependency list to recalculate state when value changes.

  return <Editor editorState={editorState} onChange={setEditorState} />;
};

const calcState = (value) => {
  return value
    ? EditorState.createWithContent(convertFromRaw(JSON.parse(value)))
    : EditorState.createEmpty();
}

Since those two hooks are used together a lot, I tend to pair them in a custom hook to encapsulate the detail.

The difference is that the custom hook runs every time the Component runs, but editorState still only updates when value changes.

Custom hook

import React, { useState, useEffect } from "react";
import { EditorState, convertFromRaw } from "draft-js";

export const useConvertEditorState = (value) => {

  const [editorState, setEditorState] = useState(calcState(value));

  useEffect(() => {
    setEditorState(calcState(value));
  }, [value]); 

  return [editorState, setEditorState];
}

const calcState = (value) => {
  return value
    ? EditorState.createWithContent(convertFromRaw(JSON.parse(value)))
    : EditorState.createEmpty();
}

Component

import React, { useState, useEffect } from "react";
import { Editor } from "draft-js";
import { useConvertEditorState } from './useConvertEditorState'

export default ({ value }) => {

  const [editorState, setEditorState] = useConvertEditorState(value);

  return <Editor editorState={editorState} onChange={setEditorState} />;
};

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744200893a4562872.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信