reactjs - 将对象链接到 redux 商店中 react-flow-renderer/react-flow 中的元素
问题描述
我一直在尝试将商店连接到我现有的工具包,useStoreState
因为useSelector
我不确定它是否适合我的用例。我想知道是否有办法将商店直接连接到我现有的 redux 工具包商店,或者我是否必须始终dispatch
将它连接到商店。
我当前的问题是我试图将活动元素放入我的商店并让每个对象链接另一个项目,但是由于useStoreState
返回整个对象,当我dispatch
进入商店时,它又变得不可序列化。这意味着,每当删除/添加元素时,它都会刷新 redux 工具包存储中存储的状态,这反过来用新对象更新存储,但所有链接的对象都会失去与该元素的连接并被删除。
我的状态示例:
[{elementID: 1, linkedText: "bla bla"}, {elementID: 2, linkedText: "bla bla for 2"}, {elementID: 3}]
当我向它添加/删除一个元素时,比如说元素 3,这会将状态重置为
[{elementID: 1}, {elementID: 2}]
哪个删除所有存储的链接文本?
我可以看看这里有什么可能的工作吗?也许能够以某种方式将结果直接存储到现有的 redux 工具包存储中?我知道easy peasy
被使用,我尝试研究如何将它连接到我也未能实现的商店。
export default connect((state) => ({ elements: state}))(EditorReactFlow);
我还应该在 redux devtools 中看到 react-flow-renderer 的内部存储吗?我只能看到我自己的应用程序,所以我想不是吗?
编辑:
目前我发送的是来自实际 react-flow-renderer 的元素,下面我已经发布了该组件。useEffect
元素被分派到我addStep()
的 redux 切片中,该切片将其解构以获取 ID 并将其存储在商店中。
function EditorReactFlow() {
const classes = useStyles();
const reactFlowWrapper = useRef(null);
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const [elements, setElements] = useState(initialElements);
const [name, setName] = useState("")
const dispatch = useDispatch();
useEffect(() =>{
dispatch(addStep(elements))
},[dispatch, elements])
const onConnect = (params) => setElements((els) => addEdge(params, els));
const onElementsRemove = (elementsToRemove) =>
setElements((els) => removeElements(elementsToRemove, els));
const onLoad = (_reactFlowInstance) =>{
_reactFlowInstance.fitView();
setReactFlowInstance(_reactFlowInstance);}
const addNode = () => {
setElements(e => e.concat({
id: getId(),
data: {label: `${name}`},
position: {x: 0, y: -5},
},
))
};
return (
<Container maxWidth="lg">
<CssBaseline />
<div className={classes.paper}> </div>
<div className="{classes.heroContent} reactflow-wrapper" ref={reactFlowWrapper}>
<ReactFlow
elements={elements}
onElementsRemove={onElementsRemove}
style={{width:'100%',height: '90vh'}}
onLoad={onLoad}
onConnect = {onConnect}
>
<Controls />
</ReactFlow>
<input type="text"
onChange={e => setName(e.target.value)}
name="title"/>
<button
type="button"
onClick={addNode}
>Add Node</button>
</div>
<RfEditorSidebar />
</Container>
);
}
export default connect(
(state) => ({ todos: state})
)(EditorReactFlow);
我使用 WYSIWYG 编辑器将数据存储到特定元素。AddStep 创建 elementID,然后editStep
将 WYSIWYG 数据存储到该特定 ID。以下是我的切片中的 theaddStep
和editStep
reducer:
addStep(state, action) {
const allSteps = action.payload;
return {
...state,
data: allSteps.map((element) => {
return { element: element.id };
}),
};
},
editStep(state: any, action) {
return {
...state,
data: state.data.map((step) =>
step.element === action.payload.element
? { ...step, step: action.payload.step }
: step
),
};
},
解决方案
EditorReactFlow
将“元素”存储为内部状态和 redux 的全局状态,这是有问题的。
- 元素存储为
EditorReactFlow
组件的内部状态:const [elements, setElements] = useState(initialElements);
- 元素也用于
dispatch
更新 Redux 全局状态的调用:dispatch(addStep(elements))
- 这是有问题的,因为这两种状态都会尝试以自己的方式更新视图/反应组件,而且通常情况下,为您的数据提供两种不同的真实来源是很糟糕的。
通常,如果一个状态需要存储在 Redux 中,那么它是通过 Redux 检索和更新的,而不是 using useState
,这不是 Redux 的一部分。
useState
请考虑使用connect
将 Redux 状态映射到props来代替,方法是执行以下操作:
消除
const [elements, setElements] = useState(initialElements);
将函数签名从更改
function EditorReactFlow() {
为function EditorReactFlow(props) {
而不是使用
elements
变量来读取元素,使用props.todos.data
删除此调用
useEffect
(有关说明,请参见下一项)useEffect(() =>{ dispatch(addStep(elements)) },[dispatch, elements])
不使用
setElements
函数更新元素列表,而是直接调用dispatch(addStep(...)) /* can be repeated for other actions*/
作为任何回调函数的一部分,例如
addNode
.
编辑:
最后,你EditorReactFlow
应该是这样的:
function EditorReactFlow(props) {
const classes = useStyles();
const reactFlowWrapper = useRef(null);
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const [name, setName] = useState("")
const dispatch = useDispatch();
let elements = props.todos.data; // Redux passes elements list through props
const onConnect = (params) => {
// Here, addEdge should be a Redux action, and needs to be dispatched
dispatch(addEdge(params, elements));
};
const onElementsRemove = (elementsToRemove) => {
// Here, removeElementsshould be a Redux action, and needs to be dispatched
dispatch(removeElements(elementsToRemove, elements));
};
const onLoad = (_reactFlowInstance) =>{
_reactFlowInstance.fitView();
setReactFlowInstance(_reactFlowInstance);}
const addNode = () => {
dispatch(addStep(elements.concat({
id: getId(),
data: {label: `${name}`},
position: {x: 0, y: -5},
}))
};
return (
<Container maxWidth="lg">
<CssBaseline />
<div className={classes.paper}> </div>
<div className="{classes.heroContent} reactflow-wrapper" ref={reactFlowWrapper}>
<ReactFlow
elements={elements}
onElementsRemove={onElementsRemove}
style={{width:'100%',height: '90vh'}}
onLoad={onLoad}
onConnect = {onConnect}
>
<Controls />
</ReactFlow>
<input type="text"
onChange={e => setName(e.target.value)}
name="title"/>
<button
type="button"
onClick={addNode}
>Add Node</button>
</div>
<RfEditorSidebar />
</Container>
);
}
export default connect(
// Ask Redux to pass Redux state to "props.todos"
// According to your "addStep" reducer, elements are stored as "state.data"
// So, elements list will be passed as "props.todo.data"
(state) => ({todos: state})
)(EditorReactFlow);
这可能会为您指明正确的方向。请让我知道这可不可以帮你。
推荐阅读
- reactjs - 单击鼠标中键时如何不打开新选项卡?
- html - 为什么我的链接没有可识别的名称?
- python - BashOperator 为其他 PythonOperators 中使用的库引发 ImportError
- python - Python制表:如何打印特定的单元格内容?
- javascript - 替代 document.createElementNS
- angular - 这不是一个功能 - Angular 5
- bash - 带有 sendmail 的 Bash 脚本在手动执行而不是从 crontab 执行时发送电子邮件
- c# - 将 ClientId 添加到“授权 API 客户端”
- shell - 需要使用参数化的通用文件创建多个文件,并使用 shell 脚本创建带有参数值的输入文件
- haskell - 一个 cabal 文件中有两个可执行文件;堆栈构建无法识别它们