发布于 2026-01-05 0 阅读
0

React Redux 与 hooks

React Redux 与 hooks

如果你还不熟悉ReduxHooks,可以先看看我之前写的其他文章,里面解释了这些主题,然后再回来阅读!我刚开始学习 Redux 的时候,觉得它涉及的各种组件和文件让人难以理解。但出乎意料的是,React Hooks 让 Redux 的使用变得简单多了。Hooks 允许我们编写更小、有时也更容易阅读的函数式组件,而 Redux Hooks 则可以让我们省去繁琐且令人困惑的 connect、mapStateToProps 和 mapDispatchToProps 方法。

使用 Hooks 将应用连接到 Redux store 的过程与不使用 Hooks 的过程基本相同。你需要创建一个接受 reducer 的 store,并将该 store 传递给用于封装应用的 Provider 组件。使用 Hooks 的主要区别在于,它可以将特定的组件连接到 store 以访问状态。

在 Hooks 出现之前,如果我们想让一个组件访问 store,我们需要使用 connect 高阶组件。

import {connect} from 'react-redux'

export default connect()(Animes)
Enter fullscreen mode Exit fullscreen mode

现在我们的动漫组件可以访问 store,如果我们想要获取状态或更改状态,我们需要使用 mapStateToProps 和 mapDispatchToProps。

import { increaseVote, decreaseVote } from '../actions';
import { connect } from 'react-redux';

const mapStateToProps = state => {
   return {
      animes: state.animes,
   };
};

const mapDispatchToProps = dispatch => {
   return {
      increaseVote: id => dispatch(increaseVote(id)),
      decreaseVote: id => dispatch(decreaseVote(id)),
   };
};

export default connect(mapStateToProps, mapDispatchToProps)(AnimeCard);
Enter fullscreen mode Exit fullscreen mode

对我来说,这些代码很容易出错,甚至一开始就忘记添加它们!请对比上面未使用 hooks 的版本和下面使用 hooks 的版本。

import { useSelector, useDispatch } from 'react-redux';
import { INCREASE_VOTE as increaseVote } from '../actions';

const dispatch = useDispatch();
const animes = useSelector(state => state.animes);
<button onClick={() => dispatch(increaseVote)}>Increase Vote</button>
Enter fullscreen mode Exit fullscreen mode

我们可以使用 `useSelector` hook 来访问 store 的状态,而不是使用 `mapStateToProps`。`useSelector` 接受 store 的当前状态作为参数,并返回你想要获取的状态片段。`useSelector` 的一个潜在问题是它使用严格相等性判断,这与之前的 `mapStateToProps` 不同,后者会检查字段是否发生变化。这可能会导致在尝试从 `useSelector` 返回对象时出现问题,因此最佳实践是针对状态的每个值调用一次 `useSelector`。我们可以使用 `useDispatch` hook 来代替 `mapDispatchToProps`,并将需要的任何 action 单独分发给 reducer。为了更好地理解 hook 和非 hook 的区别,这里展示了同一个组件的两种写法。

无钩

import React from 'react';
import { increaseVote, decreaseVote } from '../actions';
import { connect } from 'react-redux';

const AnimeCard = ({ anime, increaseVote, decreaseVote, animesInStore }) => {
   return (
      <div className="card">
         <p>{Object.keys(animesInStore).length}</p>
         <h2>Name: {anime.name}</h2>
         <p>Votes: {anime.votes}</p>
         <img src={anime.image} alt={anime.name}></img>
         <br />
         <button
            onClick={() => {
               increaseVote(anime.id);
            }}
         >
            UpVote
         </button>
         <button
            onClick={() => {
               decreaseVote(anime.id);
            }}
         >
            DownVote
         </button>
      </div>
   );
};

const mapStateToProps = state => {
   return {
      animesInStore: state.animes,
   };
};

const mapDispatchToProps = dispatch => {
   return {
      increaseVote: id => dispatch(increaseVote(id)),
      decreaseVote: id => dispatch(decreaseVote(id)),
   };
};

export default connect(mapStateToProps, mapDispatchToProps)(AnimeCard);

Enter fullscreen mode Exit fullscreen mode

带钩子

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increaseVote, decreaseVote } from '../actions';

const AnimeCard = ({ anime }) => {
   const dispatch = useDispatch();
   const animesInStore = useSelector(state => state.animes);
   return (
      <div className="card">
         <p>{Object.keys(animesInStore).length}</p>
         <h2>Name: {anime.name}</h2>
         <p>Votes: {anime.votes}</p>
         <img src={anime.image} alt={anime.name}></img>
         <br />
         <button
            onClick={() => {
               dispatch(increaseVote(anime.id));
            }}
         >
            UpVote
         </button>
         <button
            onClick={() => {
               dispatch(decreaseVote(anime.id));
            }}
         >
            DownVote
         </button>
      </div>
   );
};

export default AnimeCard;
Enter fullscreen mode Exit fullscreen mode

我们不仅节省了大约 10 行代码,而且我个人认为代码的可读性和可写性都大大提升。由于我们不再使用 connect 的高阶组件,渲染树也更加简洁。希望您喜欢这篇博文,并考虑在即将开展的项目中尝试使用 Redux 和 hooks。如有任何疑问,欢迎留言!

推荐资源:
React-Redux文档,
《将 Redux 与 React Hooks 结合使用》文章

文章来源:https://dev.to/jenkens/react-redux-with-hooks-2ie1