React Hooks 和 React-Redux 连接:让它们协同工作的最佳实践是什么?

React Hooks & React-Redux connect: What is the best practice to make them work together?

我想问一下社区,使用 react-redux connect() 和挂钩中的依赖管理结合现有代码的最佳实践是什么 useEffect().

让我们看下面的例子:

/* ... */

const mapStateToProps = (state) => ({
  todos: getTodos(state),
  currentUserId: getCurrentUserId(state)
})

const mapDispatchToProps = (dispatch) => ({dispatch})

const mapMergeProps = (stateProps, {dispatch}, ownProps) => {
  return {
    ...stateProps,
    ...dispatchProps,
    ...ownProps,
    fetchTodos: () => dispatch(fetchTodos(stateProps.currentUserId))
  }
}

const TodosListContainer = connect(mapStateToProps, mapDispatchToProps, mapMergeProps)

const TodosList = ({todos, fetchTodos, ...props}) => {

  const _fetchTodos = useCallback(fetchTodos, [])

  useEffect(() => {
    _fetchTodos()
  }, [_fetchTodos])

  return (
    <ul>
      {todos && todos.map((todo) => <li key={todo.id}>{todo.name}</li>)}
    </ul>
  )
}

上面代码中useEffect拥有所有的依赖,useCallback保证useEffect只被触发一次

然而,这似乎是一个额外的样板层:没有 useCallback,来自 connect 的 mapMergeToProps 作为 props 传递的函数将在每次状态更改时重新创建,并将触发 useEffect.

我的问题是上面的代码是否正确,在描述的上下文中有更好的方法来处理 useEffect。

我会改成下面的样子

// Leave this one like it is
const mapStateToProps = (state) => ({
  todos: getTodos(state),
  currentUserId: getCurrentUserId(state)
})

// Map the fetchTodos here
const mapDispatchToProps = {
  fetchTodos,
}

// Completely remove the mergeProps
const TodosListContainer = connect(mapStateToProps, mapDispatchToProps)

// Then use the hook like this
const TodosList = ({ todos, fetchTodos, currentUserId, ...props }) => {

  useEffect(() => {
    fetchTodos(currentUserId)
  }, [fetchTodos, currentUserId])

  return (
    <ul>
      {todos && todos.map((todo) => <li key={todo.id}>{todo.name}</li>)}
    </ul>
  )
}

这不会在每次渲染时触发 useEffect,因为道具保持不变。它删除了(一些)样板代码。我还认为它更容易理解正在发生的事情,它会 运行 当 currentUserId 发生变化时产生影响,这可能是本应发生的事情。