简体   繁体   English

为什么这段代码同时使用 useMemo 和 createSelector?

[英]Why does this code use both useMemo and createSelector?

The React-Redux documentation provides this example for when a selector is used in multiple component instances and depends on the component's props. React-Redux 文档提供了此示例,用于在多个组件实例中使用选择器并依赖于组件的道具时。

import React, { useMemo } from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const makeNumOfTodosWithIsDoneSelector = () =>
  createSelector(
    state => state.todos,
    (_, isDone) => isDone,
    (todos, isDone) => todos.filter(todo => todo.isDone === isDone).length
  )

export const TodoCounterForIsDoneValue = ({ isDone }) => {
  const selectNumOfTodosWithIsDone = useMemo(
    makeNumOfTodosWithIsDoneSelector,
    []
  )

  const numOfTodosWithIsDoneValue = useSelector(state =>
    selectNumOfTodosWithIsDone(state, isDone)
  )

  return <div>{numOfTodosWithIsDoneValue}</div>
}

export const App = () => {
  return (
    <>
      <span>Number of done todos:</span>
      <TodoCounterForIsDoneValue isDone={true} />
      <span>Number of unfinished todos:</span>
      <TodoCounterForIsDoneValue isDone={false} />
    </>
  )
}

In the function TodoCounterForIsDoneValue , why does the author wrap makeNumOfTodosWithIsDoneSelector with useMemo ?在 function TodoCounterForIsDoneValue中,为什么作者将makeNumOfTodosWithIsDoneSelectoruseMemo包裹起来? My understanding of createSelector from reselect is that it generates a memoized selector, so what is the purpose of "double" memoizing this selector?我从reselectcreateSelector的理解是它生成了一个memoized selector,那么“double”memoizing这个selector的目的是什么?

Because each component needs its own unique instance of the selector for correct memoization behavior.因为每个组件都需要自己唯一的选择器实例来正确记忆行为。 If many components use the same selector instance, and each pass in their own different arguments (such as selectThingById(state, props.itemId) ), the selector will never memoize right.如果许多组件使用相同的选择器实例,并且每个组件都传入自己不同的 arguments(例如selectThingById(state, props.itemId) ),则选择器将永远不会正确记忆。 By creating a unique instance per component, each selector can pass in its own separate args and get consistent memoization.通过为每个组件创建一个唯一的实例,每个选择器都可以传入自己单独的参数并获得一致的记忆。

Slightly unrelated to the question, but I think in this case, we can use useCallback to have the same result w/o having an extra layer of function in makeNumOfTodosWithIsDoneSelector .与问题略有无关,但我认为在这种情况下,我们可以使用useCallback来获得相同的结果,而无需在 makeNumOfTodosWithIsDoneSelector 中额外增加一层makeNumOfTodosWithIsDoneSelector

 import React, { useCallback } from 'react' import { useSelector } from 'react-redux' import { createSelector } from 'reselect' const makeNumOfTodosWithIsDoneSelector = createSelector( state => state.todos, (_, isDone) => isDone, (todos, isDone) => todos.filter(todo => todo.isDone === isDone).length ) export const TodoCounterForIsDoneValue = ({ isDone }) => { const selectNumOfTodosWithIsDone = useCallback( makeNumOfTodosWithIsDoneSelector, [] ) const numOfTodosWithIsDoneValue = useSelector(state => selectNumOfTodosWithIsDone(state, isDone) ) return <div>{numOfTodosWithIsDoneValue}</div> } export const App = () => { return ( <> <span>Number of done todos:</span> <TodoCounterForIsDoneValue isDone={true} /> <span>Number of unfinished todos:</span> <TodoCounterForIsDoneValue isDone={false} /> </> ) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM