0

我正在从头开始构建一个基于块的编辑器。我有模型

initialState = {
id,
name,
blocks: [{
id,
content: [{text: '', attributes: []}]
}]
}

在 My React Editor 中是一个组件,它将在 useReducer 中具有此状态。

const Editor: React.FC<Props> = ({ document }: Props) => {

  const reducer = (state: any, action: any) =>
    produce(state, (draft: any) => {
      switch (action.operation) {
        case ReducerActions.create: {
          const index = draft.blocks.findIndex(
            (block: any) => block.id === action.block.prevBlock,
          );
          draft.blocks.splice(index + 1, 0, action.block);
          break;
        }
        case ReducerActions.delete:
          draft.blocks = draft.blocks.filter(
            (block: any) => block.id !== action.blockId,
          );
          break;
        case ReducerActions.updateContent: {
          draft.blocks = draft.blocks.map((block: any) => {
            if (block.id === action.blockId) {
              return { ...block, content: action.content };
            }
            return block;
          });
          break;
        }
      }
    });

  const [state, dispatch]: any = useReducer(reducer, document, initialState);

  const handleOnInput = (block: any, blockAction: any) => {
    switch (blockAction.action) {

      case BlockOperations.backSpace: {
        const index = state.blocks.findIndex(
          (elem: any) => elem.id === block.id,
        );
        if (index === 0 || index === -1) {
          return;
        }
        const prevBlock = { ...state.blocks[index - 1] };
        prevBlock.content = [...prevBlock.content, ...block.content];
        dispatch({
          operation: ReducerActions.updateContent,
          blockId: prevBlock.id,
          content: prevBlock.content,
        });
        dispatch({
          operation: ReducerActions.delete,
          blockId: block.id,
        });
        break;
      }
    }
  };

  return(
    <div>
      <Toolbar/>
      <div id="editor">
        {state.blocks.map((block: any) => (
          <div key={block.id} id={block.id}>
            <Block
              key={block.id}
              block={block}
              onInput={handleOnInput}
              onSelect={handleSelect}
            />
          </div>
        ))}
      </div>
    </div>
  )
}

因此,我正在记忆 Block 组件并将所有用于 block 的道具包装在 useCallback 中以避免重新初始化。

但问题始于 OnInput 退格情况,我需要访问其他块内容并构建新内容。所以我需要最新的状态,它迫使我删除 useCallback 并使状态的所有更改重新呈现整个阻止列表。

有什么方法可以更好地分割状态并避免重新渲染所有块?

我想到的一种方法是让块管理它们的状态,并且只有在可编辑元素模糊时才会更新父块中的状态。但这会影响我们将来可能需要协作的地方,或者我们可以直接在块内容中进行 api 调用以更新特定块。由于后端架构的结构是这样的

documentModel = {
  id,
  name,
  blockIds,
}

blockModel = {
  id,
  type,
  content,
}

谢谢您的帮助。

4

0 回答 0