当前位置: 首页 > 面试题库 >

React useReducer Hook发射两次/如何将道具传递给reducer?

景俊良
2023-03-14
问题内容

前言/说明

我正在尝试将React的新挂钩函数用于我正在构建的电子商务网站,但是在解决购物车组件中的错误时遇到了问题。

我认为以我想通过使用多个Context组件保持全局状态模块化的事实作为开始讨论的重点。对于我提供的商品类型,我有一个单独的上下文组件,对于一个人的购物车中的商品,我有一个单独的上下文组件。

问题

我遇到的问题是,当我调度将组件添加到购物车的操作时,减速器将运行两次,就像我两次将商品添加到购物车一样。但是仅当它最初被渲染时,或者由于诸如显示之类的奇怪原因而被设置为hidden,然后又返回到block或由于或z-index可能的其他类似更改而发生更改。

我知道这很冗长,但它是一个很挑剔的问题,因此我创建了两个演示该问题的代码笔:

完整的例子

最小的例子

您将看到我包含一个用于切换display组件的按钮。这将有助于展示CSS与问题的相关性。

最后,请用代码笔监视控制台,这将显示所有按钮单击以及每个reducer的哪一部分已运行。该问题在完整示例中最明显,但控制台语句显示的问题在最小示例中也存在。

问题区域

我已查明该问题与以下事实有关:我正在使用useContext挂钩的状态来获取项目列表。调用了一个函数来为我的useReducer钩子生成化简器,但是仅当使用了另一个钩子时才出现,我可以使用像钩子一样不会重新评估的函数,并且没有问题,但是我还需要我以前的上下文中的信息,因此解决方法无法真正解决我的问题。

相关连结

我确定问题不是HTML问题,因此我将不包含我尝试过的HTML修复程序的链接。该问题虽然是由CSS触发的,但并非植根于CSS,因此我也不会包含CSS链接。


问题答案:

正如您指出的,原因与您链接到的我的相关答案相同。每当Provider重新渲染时,您都在重新创建化简器,因此在某些情况下,React将执行化简器以确定是否需要重新渲染Provider,如果确实需要重新渲染,它将检测到该化简器更改了,因此React需要执行新的reducer并使用它产生的新状态,而不是先前版本的reducer返回的状态。

当由于对prop或上下文或其他状态的依赖而无法仅将reducer移出功能组件时,解决方案是使用来记住您的reducer
useCallback,以便仅在其依赖关系发生变化时(例如productsList,在案件)。

要记住的另一件事是,您不必为减速器为一次调度执行两次而过分担心。React所做的假设是,Reducer通常会足够快(它们无法执行任何副作用,进行API调用等),因此在某些情况下需要重新执行它们是值得冒风险的为了避免不必要的重新渲染(如果在带有reducer的元素下面有较大的元素层次结构,这可能比reducer昂贵得多)。

这是Providerusing 的修改版本useCallback

const Context = React.createContext();
const Provider = props => {
  const memoizedReducer = React.useCallback(createReducer(productsList), [productsList])
  const [state, dispatch] = React.useReducer(memoizedReducer, []);

  return (
    <Context.Provider value={{ state, dispatch }}>
      {props.children}
    </Context.Provider>
  );
}

这是您的Codepen的修改版本:https
://codepen.io/anon/pen/xBdVMp
? editors
=
0011



 类似资料:
  • 问题内容: 我试图找到定义可以以一般方式使用的组件的正确方法: 当然,可以想象并在父组件和子组件之间进行渲染的逻辑。 对于这个问题,这是一个虚拟的实现: 问题是,每当您用于定义包装器组件时,如何将某些属性传递给其所有子组件? 问题答案: 用新道具克隆Children 您可以使用React.Children遍历子级,然后使用React.cloneElement使用新的道具(浅合并)克隆每个元素,例如

  • 我是一个相当新的反应,这是一个我正在努力解决的问题。

  • 问题内容: 我正在尝试找到定义可以以一般方式使用的某些组件的正确方法: 当然,您可以想象并作为该逻辑的示例,在父组件和子组件之间存在一种渲染逻辑。 对于这个问题,这是一个虚拟的实现: 问题是,每当您用于定义包装器组件时,如何将某些属性传递给其所有子组件? 问题答案: Cloning children with new props 您可以使用React.Children遍历子级,然后使用React.

  • 我使用的是dev-express中的react-grid库,库中有一个表组件,我们可以向它传递单元格组件,在CustomCell中,我使用的是Material UI中的菜单 在上述情况下,菜单工作良好, 但是我想要传递道具到这个组件,我尝试了以下操作 在这种情况下菜单不工作,我想知道是否有一个替代的方法来实现第二种情况。

  • 使用RxJS如何在观察者上传递新属性?所以基本上我希望道具“customProp”可以被观察到 添加更多的信息-所以基本上,我试图创建一个冷可观察的,其中制片人需要一个道具,应该来自订户 添加用法信息--coldObservable是DB连接函数,customProp是需要在DB上执行的查询

  • 我正在构建一个网页,实现了每个组件共享的通用样式(相同的背景、边框和标题样式)。所以我想我应该制作一个HOC,它接受每个组件的内部内容以及一个标题,并返回一个外部组件,它封装了这个内部组件和标题。起初,我在尝试让它发挥作用时遇到了很多问题,因为我是一个新的反应者,但现在它终于起作用了,但我仍然不明白怎么做。 这是我的HOC 这是WrappedComponent: 这是ListsComponent