使用 React Hooks 是否会大大减少在 React / Redux 中重用代码的方式?

nop*_*ole 7 reactjs redux

假设我们有 React/Redux 的旧传统方式:(如果您熟悉它,则无需扩展代码:)

import React from 'react';
import { connect } from 'react-redux';

function Count(props) {
  return (
    <div>
      <button onClick={props.increment}> + </button>
      {props.count}
      <button onClick={props.decrement}> - </button>
    </div>
  );
}

const mapStateToProps = state => ({
  count: state.count
});

const mapDispatchToProps = dispatch => ({
  increment: () => dispatch({ type: 'INCREMENT' }),
  decrement: () => dispatch({ type: 'DECREMENT' })
});

export default connect(mapStateToProps, mapDispatchToProps)(Count);
Run Code Online (Sandbox Code Playgroud)

现在,使用 React HooksuseSelector()useDispatch(),上面的代码可以这样写:

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

function Count() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  const increment = () => dispatch({ type: 'INCREMENT' });
  const decrement = () => dispatch({ type: 'DECREMENT' });

  return (
    <div>
      <button onClick={increment}> + </button>
      {count}
      <button onClick={decrement}> - </button>
    </div>
  );
}

export default Count;
Run Code Online (Sandbox Code Playgroud)

两个版本本身的工作方式完全相同,除了版本 1 不是高度可重用的Count吗?那是因为使用了不同的mapStateToProps()and mapDispatchToProps(),我们可以connect()再次使用来创建另一个CountNoodle(),现在我们已经重用了Count().

对于版本 2,Count()与它使用的 state 和 dispatch 是硬连接的,所以整个Count()是完全不可重用的。也就是说,它必须与特定状态和特定调度一起使用,但仅此而已。不是真的吗?那么上面的版本 2 不推荐吗,实际上你会有一个版本 3,它不是调用它Count()而是调用它CountNoodle()并“连接”状态和调度,然后重用Count(),这只是“展示性”?

所以它可能看起来像这样:

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

// Count() actually would be in a different file and CountNoodle.js
//   would import that file
function Count({count, increment, decrement}) {
  return (
    <div>
      <button onClick={increment}> + </button>
      {count}
      <button onClick={decrement}> - </button>
    </div>
  );
}

function CountNoodle() {
  const count = useSelector(state => state.countNoodle);
  const dispatch = useDispatch();

  const increment = () => dispatch({ type: 'INCREMENT_NOODLE' });
  const decrement = () => dispatch({ type: 'DECREMENT_NOODLE' });

  return <Count ...{count, increment, decrement} />;
  // or   return Count({count, increment, decrement});
}

export default CountNoodle;
Run Code Online (Sandbox Code Playgroud)

mar*_*son 1

我在我的文章Thoughts on React Hooks, Redux, and Separation of Concerns和我的ReactBoston 2019 演讲“Hooks, HOCs, and Tradeoffs”中解决了这个问题。

我鼓励您阅读/观看这两篇文章,但作为总结:

  • 一般来说,React hooks 会引导你采用与 HOC 不同的组织模式,其中组件更负责在内部处理自己的数据获取需求
  • 在可重用性和可测试性方面,这确实导致了与 HOC 提供的不同的权衡