当前位置: 首页 > 知识库问答 >
问题:

前端 - React多个组件基于一个信息进行组件的响应变化,请问有方便的方式进行实现吗?

岳浩
2024-10-24

image.png
需求:
组件A点击状态切换按钮,发起状态变化(需要传递数据:args),然后:
组件B1,组件B2,组件C1 都会依据此args进行相应的内容变化。

请问这样的功能一般是怎么实现?
1、是可以组件B1,B2,C1都通过监听事件实现吗?
2、还是说通过React的客户端状态实现,比如:zustand进行状态的记录来实现?(这种应该不是很好,因为不是forwardRefs来进行实时的执行)。是否有方便的方式来实现呢(比如使用三方库)?
3、请问如果是监听,是B1,B2,C1这样的子组件来直接监听好,还是B,C组件这样的组件来监听,然后再使用forwardRefs来对B1,B2,C1进行执行变化?

共有4个答案

潘青青
2024-10-24

在React中你可以使用Context API或状态管理库(如Redux)来实现组件间的通信和状态同步。以下是一个使用Context API的示例:

1. 创建Context:

// ArgsContext.js
import React, { createContext, useState } from 'react';

export const ArgsContext = createContext();

export const ArgsProvider = ({ children }) => {
  const [args, setArgs] = useState(null);
  
  return (
    <ArgsContext.Provider value={{ args, setArgs }}>
      {children}
    </ArgsContext.Provider>
  );
};

2. 在组件A中触发状态变化:

// ComponentA.js
import React, { useContext } from 'react';
import { ArgsContext } from './ArgsContext';

const ComponentA = () => {
  const { setArgs } = useContext(ArgsContext);
  
  const changeState = () => {
    const newArgs = { /* 你的数据 */ };
    setArgs(newArgs);
  };

  return (
    <button onClick={changeState}>状态切换</button>
  );
};

export default ComponentA;

3. 在组件B1、B2和C1中监听状态变化:

// ComponentB1.js
import React, { useContext } from 'react';
import { ArgsContext } from './ArgsContext';

const ComponentB1 = () => {
  const { args } = useContext(ArgsContext);
  
  return (
    <div>{JSON.stringify(args)}</div>
  );
};

export default ComponentB1;

类似地,你可以在组件B2和组件C1中使用相同的方法来获取 args 并进行相应的内容变化。

4. 在应用中使用Context Provider:

// App.js
import React from 'react';
import { ArgsProvider } from './ArgsContext';
import ComponentA from './ComponentA';
import ComponentB1 from './ComponentB1';
import ComponentB2 from './ComponentB2';
import ComponentC1 from './ComponentC1';

const App = () => {
  return (
    <ArgsProvider>
      <ComponentA />
      <ComponentB1 />
      <ComponentB2 />
      <ComponentC1 />
    </ArgsProvider>
  );
};

export default App;

这样,当组件A中的按钮被点击时,args 会通过 Context API 进行更新,组件 B1、B2 和 C1 会自动获取最新的 args 并更新其内容。确保组件间的状态同步和数据传递变得更加简单有效。

惠诚
2024-10-24

先回答问题0.请问这样的功能一般是怎么实现?
这个功能有很多种实现方式,项目中如果有状态管理库的话,一般用状态管理库实现,比如你提到的zustand,如果没有的话可以用react context API实现,当然也可以用props或forward一层层传递数据,但这样并不灵活,所以很少会这样做;

接着回答问题1.是可以组件B1,B2,C1都通过监听事件实现吗?
可以,用状态管理库、react context API、或者eventemitter之类的三方库都可以实现;

问题2.如果觉得zustand麻烦,可以用react context API,但如果对性能有较高要求的话,建议还是用zustand,也可以用eventemitter这类的发布订阅库来实现,在3个组件内对点击事件进行监听,比较常见的有mitt和eventemitter2等;

问题3.子组件直接监听好,父组件监听会引起不必要的渲染。

俞博涛
2024-10-24
  1. 事件监听
    这样做的话各个组件内部维护的是独立的状态,只是通过监听事件然后更新状态的方式做到了同步
  2. 状态管理
    多个组件共享状态可以使用 Zustand,Redux 等状态管理库
  3. 状态提升
    将公共状态提升到最近的公共父组件,在层级较多时 props 一层层传递较为繁琐
  4. Context
    类似状态提升,但是在最近公共父组件中使用 Context 提供状态,避免了 props 传递的麻烦。但是 Context 改变会导致该组件下的整个组件树重新渲染
於乐语
2024-10-24

在React中实现多个组件基于一个状态变化进行响应,通常可以通过几种方式来实现。以下是一些推荐的方法和解释:

1. 使用React Context API

React的Context API非常适合跨组件层级传递数据,而无需手动通过每个层级组件传递props。你可以创建一个Context来包含你的状态(如args)和修改这个状态的函数。然后,所有需要这个状态的组件都可以从这个Context中订阅它。

步骤

  1. 创建一个Context来保存状态和更新状态的函数。
  2. 在组件树中较高的层级(如App组件)中包裹你的Context.Provider,并传递状态值和更新函数。
  3. 在需要这个状态的组件中使用useContext钩子来订阅这个Context。

示例代码

// MyContext.js
import React, { createContext, useState } from 'react';

const MyContext = createContext({
  args: null,
  setArgs: () => {},
});

export const MyContextProvider = ({ children }) => {
  const [args, setArgs] = useState(null);

  return (
    <MyContext.Provider value={{ args, setArgs }}>
      {children}
    </MyContext.Provider>
  );
};

export default MyContext;

// 组件A, B1, B2, C1中使用MyContext

2. 使用全局状态管理库(如Redux, Zustand等)

如果你的应用很大或者状态管理变得复杂,使用全局状态管理库可能是一个好主意。这些库提供了更强大和灵活的状态管理能力。

Zustand示例

// store.js
import create from 'zustand';

const useStore = create((set) => ({
  args: null,
  setArgs: (newArgs) => set(() => ({ args: newArgs })),
}));

export default useStore;

// 组件中使用
const args = useStore(state => state.args);
const setArgs = useStore(state => state.setArgs);

3. 监听事件

虽然监听事件(如使用useEffect来监听Redux store的变化或自定义事件)是一种可行的方法,但它通常不如使用Context或全局状态管理库那么直接和高效。特别是,如果你正在监听Redux store的变化,你可能需要使用Redux的useSelector钩子。

4. 组件间通信方式

  • 直接监听 vs 组件B/C监听:如果B1, B2, C1直接依赖于args,则它们应该直接监听这个状态的变化。如果它们共享一些共同的行为或状态,可以考虑将它们包裹在一个共同的父组件(如B或C)中,但这个父组件也应该是基于Context或全局状态来管理其子组件的状态。
  • forwardRefsforwardRefs主要用于将refs从父组件传递到子组件,而不是用于状态管理。在这个场景中,它可能不是最直接或最有效的解决方案。

结论

对于你的需求,推荐使用React的Context API或全局状态管理库(如Zustand)来实现跨组件的状态共享和响应。这些方法不仅简化了状态管理的复杂性,还提高了组件间的解耦程度。

 类似资料:
  • 问题内容: 我刚开始使用ReactJS,但对我遇到的问题有些困惑。 我的应用程序本质上是一个带有过滤器的列表和一个用于更改布局的按钮。目前我使用的三个组成部分:,和,现在很明显,当我更改设置,在我想引起一些方法来更新我的看法。 如何使这三个组件相互交互,或者我需要可以对其进行更改的某种全局数据模型? 问题答案: 最佳方法取决于您计划如何安排这些组件。现在想到的一些示例场景: 是的子组件 这两个和是

  • 我的数组如下所示: 我想根据它们的第二个和第三个值按升序对这些数组进行排序,但第三个数值为负数的数组必须递减排序,并放在其他数组之后 结果应该是这样的: 怎么做才能尽可能的优化呢?

  • 我想根据另一个数组(索引)的排序顺序迭代两个数组(A,B),在本例中是10、34、32、21。 为这里的坏例子道歉。我已经更新了索引数组以消除混乱。 预期投入产出 但是,如果我将最后一行末尾的indexes[s]更改为indexes[indexOrder.indexOf(s)]。排序将给出错误的结果。如果ArrayList的索引与其值相同,为什么indexOf(s)会给出与s不同的结果。

  • 我正在使用在我的应用程序中实现一个亮/暗主题。不确定这是否太重要了,但我正在使用打字脚本。我还是一个新的反应和ts。 当组件是一个基本的HTML元素时,这是很简单的: 或者在自定义组件上(我可能拥有也可能不拥有该类型)。这里,我将从中对进行样式化: 然而,当我需要对没有显式呈现的组件进行样式化时,我会遇到麻烦。对于上面的例子,我显然在代码的某个地方有: 但是关于样式呢,比如说我自己不呈现的的子级?

  • 请问一下有什么思路这样做到? 比如: 我有一个组件A(内有状态), 然后在我的一个容器面板中,我想要自由增加/删除组件A(也就是可以有多个组件A) 这里我有一点疑惑,每个组件都有名称一样的状态,我怎么做区分呢?特别是如果要结合zustand去保存状态,那么这里就重复了状态名。

  • 请问下是否有方法或者现有的组件可以做到子组件都有一定的间隔? 我在使用antd的时候 默认,两个按钮的布局是紧挨着的, 1、请问是否有一个父组件(比如:antd的某个组件)可以让它们进行间隔开来? 2、是否有方便的方法比如:写一个父div里面有style,让所有的子组件进行间隔开来?

  • 问题内容: 也许我只是没有正确阅读规范,或者我的心态仍然停留在较早的同步方法上,但是Go 中发送一种类型作为接收其他类型作为响应 的正确方法 是什么? 我想到的一种方法是 该高速缓存对于此示例并不是真正必需的,但否则将导致数据争用。 这是我应该做的吗? 问题答案: 有很多可能性,这取决于解决问题的最佳方法。当您从某个渠道收到消息时,没有什么比默认的响应方式更好的了–您需要自己构建流程(肯定是在问题

  • 我想要做到如下的面包屑: 我的逻辑代码: 如上,我像要使用一个方法来进行遍历组成Breadcrumb.Item。 请问应该如何做呢?这里不是JSX中,是一个方法中,如何在方法中进行组合JSX?