reactjs 最有效的数据处理方式

7lrncoxx  于 2023-10-17  发布在  React
关注(0)|答案(2)|浏览(107)

我试图理解处理大量子组件时的开销,使用reducer从状态中提取数据。
考虑到这三种不同的方法,哪一种是最有效的?我的直觉告诉我选择二。但我说得对吗而且,在它被编译之后,它会有那么大的不同吗?

选项一

// call the reducer once, and pass all data

const MainComponent = () => {
  const { data } = useMyReducer()

  return (
    <SubComponent id="one" data={data} />
    <SubComponent id="two" data={data} />
    <SubComponent id="three" data={data} />
    <SubComponent id="four" data={data} />
    // and many more
  )
}

const SubComponent = ({id, data}) => {
  const myData = data[id]

  return (
    <div>{myData}</div>
  )
}

选项二

// call the reducer once, and pass required data only

const MainComponent = () => {
  const { data } = useMyReducer()

  return (
    <SubComponent id="one" data={data.one} />
    <SubComponent id="two" data={data.two} />
    <SubComponent id="three" data={data.three} />
    <SubComponent id="four" data={data.four} />
    // and many more
  )
}

const SubComponent = ({id, data}) => {

  return (
    <div>{data}</div>
  )
}

选项三

// call the reducer in the subcomponent

const MainComponent = () => {

  return (
    <SubComponent id="one" />
    <SubComponent id="two" />
    <SubComponent id="three" />
    <SubComponent id="four" />
    // and many more
  )
}

const SubComponent = ({id}) => {
  const { data } = useMyReducer()
  const myData = data[id]

  return (
    <div>{myData}</div>
  )
}

edit:显示useMyReducer代码-本质上是访问上下文,还有react的useReducercreateContext

import { useContext } from 'react'
import { MyContext } from './context'

const useMyReducer = () => {
    const context = useContext(MyContext)

    if (context === undefined) {
        throw new Error('useMyReducer must be used within MyContext')
    }

    return context
}

export default useMyReducer
// in context.js
export const MyContext = createContext(initialState)
export const MyProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, {})
  ... // reducer functions

  const value = { state, // plus functions etc }

  return <MyContext.Provider value={value}>{children}</MyContext.Provider>
}
tkclm6bt

tkclm6bt1#

是的!你是对的,选择2是最正确的方法,因为:
1-仅将所需数据传递到每个组件,避免传递不必要的数据。
2-避免像选项3那样多次调用reducer。在每个组件中调用useMyReducer()可能会影响性能。
3-保持关注点的分离-父组件处理数据获取,子组件只是呈现。
编译后,性能差异可能会减少,但选项2仍然通过仅向每个组件传递相关数据来保持代码的整洁和可维护性。
选项1将不必要的数据传递给每个子节点,而选项3则多次调用reducer。
%% ADDED %%
比较选项2和选项3:

  • Option 2在父组件中调用一次reducer,而Option 3在每个子组件中调用reducer
  • 在选项2中,子组件很简单,只呈现数据,但在选项3中,每个子组件都处理数据获取
7bsow1i6

7bsow1i62#

比较#1和#2,你的例子很简单,没有什么区别。但在更复杂的例子中,我通常倾向于#2,原因如下:

  1. React.memo
    在某个时候,如果SubComponent的任何属性都没有更改,您可能会决定通过跳过SubComponent的呈现来提高性能。如果使用选项1,则对数据的任何部分进行更改都将中断所有子组件上的备忘录。如果使用选项2,则只有一个子组件会中断其备忘录化
import { memo } from 'react';
// ...
const SubComponent = memo(({id, data}) => {
  return (
    <div>{data}</div>
  )
})

1.重用性
如果组件只接受完成其工作所需的最小数据量(即选项2),那么您可以在更广泛的情况下使用该组件。如果您发现自己在一个页面上只有一个组件的数据,而这个组件没有 Package 在容器对象中,那么它可以将其传递到SubComponent中,而不必首先将其 Package 在对象中。
关于备选方案3:我最初的答案假设它会导致每个组件都有自己的状态。但是看到代码,我错了。钩子使用useContext访问提供程序中的共享状态。
选项#3的行为与选项#1类似。如果数据的任何部分发生更改,那么所有子组件都必须重新渲染,即使它们使用React.memo。而且可重用性将降低,因为现在它只能使用来自一个源的数据。

相关问题