React 中函数式 Observable 模式的绝对最简单示例

Absolute simplest example of an Functional Observable pattern in React

任何人都可以提供一个在 ReactJS 中观察到的愚蠢简单的例子吗?

基本上我想将消息从一个组件传递到另一个组件。

Google 搜索让我陷入了 RxJs、Redux、Hooks、共享内存、基于 Class 的组件和其他相关主题的困境。

以如下结构为例:

    A
   / \
  B   C
 /\
D  E

我只需要从组件 D 向 C 发送 true/false 消息。

这在 React 中天生就很复杂吗? tyvm,基思 :^)

RxJS

Redux-observable 使用 ReactiveX observables 但我不认为它是 React 应用程序最常用的方法。

反应状态

React 状态(this.state 或 useState)仅从父级传递到子级,因此当 D 和 C 需要状态时,它必须在一个共同的祖先 A 中进行管理。这意味着 A 需要传递 props把B不需要的东西传给B,只有这样B才能把它传给C。这叫做道具钻孔,被认为是不好的,所以不是最好的选择。

Redux 和 react-redux

Redux store 是一个事件存储,你可以调度动作(事件),reducers 或中间件将作用于这些动作以更新状态(reducers)或产生副作用(通常用中间件完成)。组件可以使用选择器从状态 useSelector(selectorFunction) 获取数据,之前使用 HOC connect 但挂钩要简单得多。

当调度导致状态更改的动作时,所有 selectorFunction 函数都会被 react-redux 调用,如果它们的 return 值与上一个 运行 不同,则它将重新渲染使用 useSelector 的组件。

如果你必须实现复杂的需求,Redux 是一个很好的选择,因为 CQRS/event 存储模式可以很容易地将操作(指示发生了什么)与缩减器(发生事情时做什么)分开,你可以用选择器查询商店(常用reselect)。

上下文

对于没有复杂要求的应用程序,您可以使用上下文,无论何时更改上下文,具有 useContext 的组件都会重新呈现。下面是一个简单的例子。

const BoolContext = React.createContext();
const BoolProvider = ({ children }) => {
  //set bool message to true
  const [bool, setBool] = React.useState(true);
  const toggle = React.useCallback(
    () => setBool((b) => !b),
    []
  );
  return (
    // set value of context to {bool, toggle}
    <BoolContext.Provider value={{ bool, toggle }}>
      {children}
    </BoolContext.Provider>
  );
};

const D = () => {
  const { bool, toggle } = React.useContext(BoolContext);
  return <button onClick={toggle}>D:{String(bool)}</button>;
};
const C = () => {
  const { bool, toggle } = React.useContext(BoolContext);
  return <button onClick={toggle}>C:{String(bool)}</button>;
};
//removed E as it does not do anything to demonstrate context
const B = () => ( <D /> )

const A = () => {
  return (
    <BoolProvider>
      <B />
      <C />
    </BoolProvider>
  );
};

ReactDOM.render(<A />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>