将对象链接到 redux 存储中 react-flow-renderer/react-flow 中的元素
Linking objects to elements in react-flow-renderer/react-flow in redux store
我一直在尝试将商店连接到我现有的工具包,useStoreState
充当 useSelector
我不确定它是否适合我的用例。
我想知道是否有办法将商店直接连接到我现有的 redux 工具包商店,或者我是否必须始终 dispatch
它到商店。
我当前的问题是,我正在尝试将活动元素放入我的商店并让每个对象链接另一个项目,但是由于 useStoreState
returns 整个对象又变成非当我 dispatch
它进入商店时可序列化。这意味着只要一个元素是 deleted/added 它就会刷新 redux 工具包存储中存储的状态,这反过来会用新对象更新存储但是所有链接的对象都会失去与该元素的连接并被删除。
我所在州的示例:
[{elementID: 1, linkedText: "bla bla"}, {elementID: 2, linkedText: "bla bla for 2"}, {elementID: 3}]
我 add/remove 一个元素的那一刻,比如说元素 3,这会将状态重置为
[{elementID: 1}, {elementID: 2}]
哪个删除所有存储的链接文本?
这里有什么可行的工作可供我参考吗?也许能够以某种方式将结果直接存储到现有的 redux 工具包存储中?我知道使用了 easy peasy
,我尝试研究如何将它连接到我也未能实现的商店。
export default connect((state) => ({ elements: state}))(EditorReactFlow);
我还应该在 redux devtools 中看到 react-flow-renderer 的内部存储吗?我只能看到我自己的应用程序,所以我想不是吗?
编辑:
目前我派发的是实际react-flow-renderer中的Elements,下面贴出了组件。在 useEffect
上,元素被分派到我的 redux 切片中的 addStep()
,它解构它以获取 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);
我使用所见即所得编辑器将数据存储到特定元素。 AddStep 创建 elementID,然后 editStep
将所见即所得数据存储到该特定 ID。下面是我切片中的 addStep
和 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 检索和更新状态,而不使用 useState
,这不是 Redux 的一部分。
请考虑 using connect
to map Redux states to props 而不是 useState
,方法如下:
删除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);
这可能会为您指明正确的方向。如果这有帮助,请告诉我。
我一直在尝试将商店连接到我现有的工具包,useStoreState
充当 useSelector
我不确定它是否适合我的用例。
我想知道是否有办法将商店直接连接到我现有的 redux 工具包商店,或者我是否必须始终 dispatch
它到商店。
我当前的问题是,我正在尝试将活动元素放入我的商店并让每个对象链接另一个项目,但是由于 useStoreState
returns 整个对象又变成非当我 dispatch
它进入商店时可序列化。这意味着只要一个元素是 deleted/added 它就会刷新 redux 工具包存储中存储的状态,这反过来会用新对象更新存储但是所有链接的对象都会失去与该元素的连接并被删除。
我所在州的示例:
[{elementID: 1, linkedText: "bla bla"}, {elementID: 2, linkedText: "bla bla for 2"}, {elementID: 3}]
我 add/remove 一个元素的那一刻,比如说元素 3,这会将状态重置为
[{elementID: 1}, {elementID: 2}]
哪个删除所有存储的链接文本?
这里有什么可行的工作可供我参考吗?也许能够以某种方式将结果直接存储到现有的 redux 工具包存储中?我知道使用了 easy peasy
,我尝试研究如何将它连接到我也未能实现的商店。
export default connect((state) => ({ elements: state}))(EditorReactFlow);
我还应该在 redux devtools 中看到 react-flow-renderer 的内部存储吗?我只能看到我自己的应用程序,所以我想不是吗?
编辑:
目前我派发的是实际react-flow-renderer中的Elements,下面贴出了组件。在 useEffect
上,元素被分派到我的 redux 切片中的 addStep()
,它解构它以获取 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);
我使用所见即所得编辑器将数据存储到特定元素。 AddStep 创建 elementID,然后 editStep
将所见即所得数据存储到该特定 ID。下面是我切片中的 addStep
和 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 检索和更新状态,而不使用 useState
,这不是 Redux 的一部分。
请考虑 using connect
to map Redux states to props 而不是 useState
,方法如下:
删除
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);
这可能会为您指明正确的方向。如果这有帮助,请告诉我。