Reactjs 将对象链接到react-flow渲染器中的元素/redux存储中的react-flow

Reactjs 将对象链接到react-flow渲染器中的元素/redux存储中的react-flow,reactjs,react-redux,redux-toolkit,Reactjs,React Redux,Redux Toolkit,我一直在尝试将存储连接到我现有的工具包,useStoreState充当useSelector我不确定它是否适合我的用例。 我想知道是否有一种方法可以将商店直接连接到我现有的redux toolkit商店,或者我是否必须始终将它分派到商店 function EditorReactFlow() { const classes = useStyles(); const reactFlowWrapper = useRef(null); const [reactFlowInstance, se

我一直在尝试将存储连接到我现有的工具包,
useStoreState
充当
useSelector
我不确定它是否适合我的用例。 我想知道是否有一种方法可以将商店直接连接到我现有的redux toolkit商店,或者我是否必须始终
将它分派到商店

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);
我当前的问题是,我试图将活动元素放入我的存储中,并使每个对象链接到另一个项目,但是由于
useStoreState
返回整个对象,因此当我
dispatch
将其发送到存储中时,它将变成不可序列化的。这意味着,无论何时删除/添加元素,它都会刷新redux toolkit存储中的存储状态,这反过来会使用新对象更新存储,但所有链接的对象都会失去与该元素的连接并被删除

我所在州的示例:

[{elementID: 1, linkedText: "bla bla"}, {elementID: 2, linkedText: "bla bla for 2"}, {elementID: 3}]
当我添加/删除一个元素时,比如说元素3,它会将状态重置为

[{elementID: 1}, {elementID: 2}]
哪个选项会删除所有存储的链接文本

这附近有什么我可以看的工作吗?也许能够以某种方式将结果直接存储到现有的redux toolkit存储中?我知道使用了easy peasy,我试着研究如何将它连接到商店,但我也没能实现

export default connect((state) => ({ elements: state}))(EditorReactFlow);
我还应该在redux开发工具中看到react-flow渲染器的内部存储吗?我只能看到我自己的应用程序,所以我想不会吧

编辑:

目前我分派的是来自实际react流渲染器的元素,下面我已经发布了组件。在
useffect
上,元素被分派到我的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);

EditorReactFlow
将“元素”存储为内部状态和redux的全局状态,这是有问题的

  • 元素存储为
    EditorReactFlow
    组件的内部状态:
    const[Elements,setElements]=useState(initialElements)
  • 元素也用于
    dispatch
    调用以更新Redux的全局状态:
    dispatch(addStep(Elements))
  • 这是有问题的,因为这两种状态都会尝试以各自的方式更新视图/反应组件,而且通常情况下,数据有两种不同的真实来源是不好的
通常,如果一个状态需要存储在Redux中,则通过Redux检索和更新它,而不使用
useState
,这不是Redux的一部分

而不是<代码> UsStuts<代码>,请考虑通过以下方式映射ReDux状态:

  • 移除
    const[elements,setElements]=useState(initialElements)

  • 将函数签名从
    function EditorReactFlow(){
    更改为
    function EditorReactFlow(props){

  • 使用
    props.todos.data

  • 删除对
    useffect
    的调用(请参阅下一项以了解解释)

  • 直接调用

    dispatch(addStep(…)/*可重复用于其他操作*/

    作为任何回调函数的一部分,例如
    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);
函数编辑器或reactflow(道具){
const classes=useStyles();
const reactFlowWrapper=useRef(null);
常量[reactFlowInstance,setReactFlowInstance]=useState(null);
const[name,setName]=useState(“”)
const dispatch=usedpatch();
let elements=props.todos.data;//Redux通过props传递元素列表
常量onConnect=(参数)=>{
//在这里,addEdge应该是一个Redux操作,并且需要被调度
调度(添加(参数、元素));
};
常量OneElementsRemove=(elementsToRemove)=>{
//在这里,RemoveElements应该是一个Redux操作,并且需要进行调度
分派(移除元素(元素StoreMove,元素));
};
const onLoad=(\u reactFlowInstance)=>{
_reactFlowInstance.fitView();
setReactFlowInstance(_reactFlowInstance);}
const addNode=()=>{
调度(addStep)(elements.concat({
id:getId(),
数据:{label:`${name}`},
位置:{x:0,y:-5},
}))
};
返回(
setName(e.target.value)}
name=“title”/>
添加节点
);
}
导出默认连接(
//要求Redux将Redux状态传递给“props.todos”
//根据“addStep”缩减器,元素存储为“state.data”
//所以,元素列表将作为“props.todo.data”传递
(state)=>({todos:state})
)(EditorReactFlow);

这可能会为您指明正确的方向。请让我知道这是否有帮助。

您好,您可以分享您发送的操作的代码吗?如果没有其他信息,很难知道为什么状态会被这样覆盖。您好,感谢您的回复,我已经更新了代码,以显示完整的组件和所有还原器。是的,这一切都很有道理。谢谢,我想我现在肯定可以继续了。谢谢。我必须将它应用到大多数处理程序中,以便他们更新我自己的全局redux存储并从本质上使用它。
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);