最新的 React 和 Redux 的更新,增加了新的功能 Hooks。现在我们就可以使用 Hooks替换 React Redux 的 connect 高阶组件。下面我们就来看一下如何使用 Redux Hooks 然后探索 下一些拓展和方法
Hooks 在 React 16.8 中添加的新功能,允许你直接访问 state, React 生命周期方法和一 些其它在函数式组件的好处(在类组件中才有的)。
下面的例子,一个类组件
class Count extends React.Component {
readonly state = {
count: 0,
}
add = () => {
this.setState({count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Count: { this.state.count } </p>
<button onClick={this.add}>Add</button>
</div>
)
}
}
上面的例子,可以使用 Hooks 写成 函数式组件:
const Count = () => {
// state variable, initialized to 0
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Add</button>
</div>
)
}
可以看出,下面的代码更加简洁并且允许成员复用组件而不必转换成类组件,当他们想访问 state 或者使用 React 的生命周期方法。这里不会全面的介绍关于 Hooks 的信息。所以,你可以查阅优秀的 Hooks 文档,如果你想学习更多。
React Redux 现在有了自己的 useSelector 和 useDispatch Hooks ,他们可以用来替代 connect 高阶组件。
useSelector 类似 connect 的 mapStateToProps。 你传递给它一个函数来获取 Redux store state 并且返回你感兴趣的状态部分
useDispatch 取代 connect 的 mapDispatchToProps 但是它更轻量。 它所作的全部就是返回 store 的 dispath 方法,所以你可以自己派发 actions。我非常喜欢这个改变,因为绑定 action creators 可能会对一些 React Redux 新手比较困惑。
好了,让我们来把一个类组件使用 connect ,转换成使用 Hooks。
使用 connect:
import React from "react";
import { connect } from "react-redux";
import { addCount } from "./store/counter/actions";
export const Count = ({ count, addCount }) => {
return (
<main>
<div>Count: {count}</div>
<button onClick={addCount}>Add to count</button>
</main>
)
}
const mapStateToProps = state => ({
count: state.counter.count
});
const mapDispatchToProps = { addCount };
export default connect(mapStateToProps, mapDispatchToProps)(Count);
好了,我们使用 React Redux Hooks 取代 connect 来实现:
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { addCount } from "./store/counter/actions";
export const Count = () => {
const count = useSelector(state => state.counter.count);
const dispatch = useDispatch();
return (
<main>
<div>Count: {count}</div>
<button onClick={() => dispatch(addCount())}>Add to count</button>
</main>
);
};
我很喜欢使用 Redux Hooks 相比于包装的 connect 高阶组件它的概念很少,另一个好处是,相较于高阶组件,它没有被称作"Virtual DOM of death"。
useSelector 和 mapStateToProps 最大的分歧,它使用了严格的对象检查(对象的引用相等)===,来决定组件是否需要重新渲染,例如下面的代码片段
const { count, user } = useSelector(state => ({
count: state.counter.count,
user: state.user,
}))
useSelector 每一次调用都会返回一个新的对象。当 store 更新时,React Redux 都会重新运行 useSelector,并且一个新的对象返回,更新组件,这不是我们需要的
一个简单的规则避免使用单一的对象引用 useSelector ,你需要的
const count = useSelector(state => state.counter.count)
const user = useSelector(state => state.user)
或者,当返回一个对象容器包含多个值,显示的告诉 useSelector 使用隐式比较,传递比较方法给第二个参数。
import { shallowEqual, useSelector } from "react-redux";
const { count, user } = useSelector(state => ({
count: state.counter.count,
user: state.user,
}), shallowEqual);