我正在从头开始构建一个基于块的编辑器。我有模型
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,
}
谢谢您的帮助。