如何在两个反应组件之间建立共享状态?

时间:2016-08-11 15:56:22

标签: javascript reactjs react-router

我有2个需要共享状态的反应组件,react-router显示组件A,它接受一些输入并将其添加到其状态,在状态成功更新后,我想重定向到组件B,其中在我向api提交post请求以保存来自组件A和B的数据之前,用户添加了一些输入并更新了与组件A相同的状态以构建具有A和B输入的对象。如何实现此目的,有没有办法使用react-router,还是我必须在组件之间建立父/子关系?

5 个答案:

答案 0 :(得分:12)

您想要的是实现一些存储您的状态的对象,可以使用回调函数进行修改。然后,您可以将这些函数传递给React组件。

例如,您可以创建商店:

function Store(initialState = {}) {
  this.state = initialState;
}
Store.prototype.mergeState = function(partialState) {
  Object.assign(this.state, partialState);
};

var myStore = new Store();

ReactDOM.render(
  <FirstComponent mergeState={myStore.mergeState.bind(myStore)} />,
  firstElement
  );
ReactDOM.render(
  <SecondComponent mergeState={myStore.mergeState.bind(myStore)} />,
  secondElement
  );

现在,FirstComponentSecondComponent实例都可以调用this.props.mergeState({ . . .})将状态分配给同一商店。

我将Store.prototype.getState作为练习留给读者。

请注意,您始终可以将商店(myStore)本身传递给组件;它只是感觉不那么反应。

以下是一些可能感兴趣的文档:

React Docs: "Communicate Between Components"

  

用于两个没有组件的组件之间的通信   亲子关系,您可以设置自己的全局事件   系统。订阅componentDidMount()中的事件,取消订阅   componentWillUnmount(),并在收到事件时调用setState()。   Flux模式是安排这种方式的可能方式之一。

答案 1 :(得分:4)

组件之间的依赖关系类型将定义最佳方法。

例如,如果您计划拥有一个中央商店,redux是一个很好的选择。然而,其他方法也是可能的:

  • 父母与孩子

    1. 道具
    2. 实例方法
  • Child to Parent

    1. 回调功能
    2. 事件冒泡
  • 与兄弟姐妹同胞

    1. 父组件
  • Any to Any

    1. 观察员模式
    2. 全球变量
    3. 上下文

请找到更多detailed information about each of the approaches here

答案 2 :(得分:1)

您可以设置父子关系,然后可以将数据作为道具传递给子组件。

否则,如果您想在两个与(父/子)无关的组件之间创建互动,您可以查看flux或更好redux

我会说你应该使用redux。See Here why

答案 3 :(得分:0)

您可以构建自定义的React钩子以在组件之间共享state,我做了一个here。您可以通过下载use-linked-state.js文件来使用它。

导入useStateGateway挂钩之后,在父组件中声明一个网关,并将其传递给子组件

import {useStateGateway} from "use-linked-state";
const myGateway = useStateGateway({partA:null, partB:null});
return (
  <>
    <ComponentA gateway={myGateway}>
    <ComponentB gateway={myGateway}>
    <ComponentPost gateWay={myGateway}>
  </>
  )

然后,您可以通过自定义useLinkedState挂钩访问这三个组件之间的共享状态

import { useLinkedState } from "use-linked-state";

export default function ComponentA({gateway}){

  const [state, setState] =  useLinkedState(gateway);

  <your logic>

}

按照您的逻辑,ComponentAComponentB将负责它们在共享对象{partA:"filled by ComponentA", partB:"filled by componentB"}中的角色。 最后,如果共享对象的ComponentPostpartA有效,则partB发布结果。

通过这种方式,您可以组成组件并在它们之间建立连接以相互交谈。

答案 4 :(得分:0)

use-between钩子是在多个组件之间使用共享状态而不将应用程序的代码重写到某些状态管理系统的最简单方法。

Try this example in codesandbox

import React, { useState } from "react";
import { useBetween } from "use-between";

// Make a custom hook with your future shared state
const useFormState = () => {
  const [username, setUsername] = useState("");
  const [email, setEmail] = useState("");
  return {
    username, setUsername, email, setEmail
  };
};

// Make a custom hook for sharing your form state between any components
const useSharedFormState = () => useBetween(useFormState);

const ComponentA = () => {
  // Use the shared hook!
  const { username, setUsername } = useSharedFormState();
  return (
    <p>
      Username: <input value={username} onChange={(ev) => setUsername(ev.target.value)} />
    </p>
  );
};

const ComponentB = () => {
  // Use  the shared hook!
  const { email, setEmail } = useSharedFormState();
  return (
    <p>
      Email: <input value={email} onChange={(ev) => setEmail(ev.target.value)} />
    </p>
  );
};

const ComponentC = () => {
  // Use shared hook!
  const { email, username } = useSharedFormState();
  return (
    <p>
      Username: {username} <br />
      Email: {email}
    </p>
  );
};

export const App = () => (
  <>
    <ComponentA />
    <ComponentB />
    <ComponentC />
  </>
);
  • 首先,我们创建useFormState自定义钩子作为状态的来源。
  • 在下一步中,我们创建useSharedFormState钩子,该钩子在内部使用useBetween钩子。该钩子可以在任何可以读取或更新共享状态的组件中使用!
  • 最后一步是在组件中使用useSharedFormState

useBetween是调用任何挂钩的一种方法。但是这样一来,状态将不会存储在React组件中。对于相同的钩子,调用的结果将相同。因此,我们可以在不同的组件中调用一个钩子,并在一种状态下协同工作。更新共享状态时,使用共享状态的每个组件也会被更新。