【问题标题】:Use context for communication between components at different level使用上下文在不同级别的组件之间进行通信
【发布时间】:2022-12-18 21:02:43
【问题描述】:

我正在构建我的应用程序的设置页面,其中我们有一个通用的SettingsLayout(父组件),它用于所有设置页面。此布局的一个特殊性是它包含一个 ActionsBar,其中存在用于保存数据的提交/保存按钮。

然而,这个SettingsLayout的内容对于每个页面都是不同的,因为每个页面都有不同的形式和不同的交互方式。为了将数据持久化到后端,我们使用了在子组件之一中调用的 Apollo Mutation,这就是无法访问 ActionsBar 保存按钮的原因。

对于这个实现,我认为 React Context 是最合适的方法。一开始,我想到了使用 Ref,在每次不同的渲染中使用提交处理函数更新它,以了解变化。

我已经实现了一个 codesandbox,其中包含一个非常小且精简的应用程序示例,以试图更好地说明和阐明我尝试实现的内容。

https://codesandbox.io/s/romantic-tdd-y8tpj8?file=/src/App.tsx

这种方法有什么注意事项吗?

import React from "react";
import "./styles.css";

type State = {
  onSubmit?: React.MutableRefObject<() => void>;
};

type SettingsContextProviderProps = {
  children: React.ReactNode;
  value?: State;
};

type ContextType = State;

const SettingsContext = React.createContext<ContextType | undefined>(undefined);

export const SettingsContextProvider: React.FC<SettingsContextProviderProps> = ({
  children
}) => {
  const onSubmit = React.useRef(() => {});

  return (
    <SettingsContext.Provider value={{ onSubmit }}>
      {children}
    </SettingsContext.Provider>
  );
};

export const useSettingsContext = (): ContextType => {
  const context = React.useContext(SettingsContext);

  if (typeof context === "undefined") {
    /*throw new Error(
      "useSettingsContext must be used within a SettingsContextProvider"
    );*/

    return {};
  }

  return context;
};

function ExampleForm() {
  const { onSubmit } = useSettingsContext();

  const [input1, setInput1] = React.useState("");
  const [input2, setInput2] = React.useState("");

  onSubmit.current = () => {
    console.log({ input1, input2 });
  };

  return (
    <div className="exampleForm">
      <input
        placeholder="Input 1"
        onChange={(event) => setInput1(event.target.value)}
      />

      <input
        placeholder="Input 2"
        onChange={(event) => setInput2(event.target.value)}
      />
    </div>
  );
}

function ActionsBar() {
  const { onSubmit } = useSettingsContext();

  return (
    <section className="actionsBar">
      <strong>SETTINGS</strong>

      <button onClick={() => onSubmit?.current()}>Save</button>
    </section>
  );
}

export default function App() {
  return (
    <div className="App">
      <SettingsContextProvider>
        <ActionsBar />

        <ExampleForm />
      </SettingsContextProvider>
    </div>
  );
}

【问题讨论】:

  • 将使用此(或任何更好的方法)的模式的另一个示例是典型的浮动操作按钮。

标签: reactjs typescript react-hooks next.js react-context


【解决方案1】:

我在这种方法中看到的主要警告是,当您只需要对提交事件做出反应时,您会更改整个提交功能。我认为事件是关键。

您的方法工作正常,但没有扩展点,用于验证等情况。

所以我建议以任何形式(更好地支持类型)使用 EventEmitter 作为上下文值,例如沟通渠道。

这是您的 codesandbox 的一个分支,说明了这种方法: https://codesandbox.io/s/friendly-fog-qlrusj?file=/src/App.tsx

【讨论】:

    猜你喜欢
    • 2020-01-18
    • 2020-08-30
    • 2012-09-30
    • 2019-07-31
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-08-11
    相关资源
    最近更新 更多