在使用 Redux 编写前端应用时,Action Creators 是非常重要的一环。它们是用来创建 Action 对象的工厂函数,将应用的状态变更逻辑集中在一处,方便维护和 debugging。但是在实际开发中,我们经常会遇到一些 Action Creators 的陷阱,这篇文章将介绍这些陷阱的原因和解决方案。
陷阱 1:在 Action Creators 中直接调用异步操作
在 Action Creators 中进行异步操作是很常见的操作,比如调用后台 API,但这种操作在 Redux 中是行不通的。因为 Action Creators 必须是同步函数,如果你在其中调用了异步操作,那么它将返回一个 Promise,而不是 Action 对象。这会导致后面的 Redux 流程不能正常进行,以及出现奇怪的错误信息。
例如,下面的 Action Creators 中调用了一个异步的 fetch 函数:
-- -------------------- ---- ------- -------- ----------- - ------ -------- -- - ------------------ -------------- -- ---------------- ---------- -- - ---------- ----- --------------------- -------- ---- -- -- - -
这种写法看起来非常合理,因为我们实际上需要进行异步操作才能获得数据。但是,这个 Action Creators 并不会返回一个 Action 对象,而是返回一个包含 Promise 对象的函数。这会导致我们在组件中调用这个 Action Creators 时遇到各种问题。
解决方案
解决这个问题的关键在于理解 Action Creators 必须是同步函数这个特性。而在 Redux 中,唯一能够接受异步操作的是 Middleware,我们可以通过将异步操作放到 Middleware 中来解决这个问题。
比如,我们可以使用 redux-thunk Middleware,将异步操作移到 Middleware 中:
-- -------------------- ---- ------- ------ - ------------ --------------- - ---- ------- ------ --------------- ---- ------------- ------ ----------- ---- ------------ ----- ----- - ------------ ------------ -------------------------------- - -------- ----------- - ------ -------- -- - ------------------ -------------- -- ---------------- ---------- -- - ---------- ----- --------------------- -------- ---- -- -- - -
这种写法会在调用 Action Creators 之后,将异步操作放到 thunkMiddleware 中处理。如果异步操作成功,它会向 Redux 中 dispatch 一个 Action 对象,触发状态的更新。
陷阱 2:在 Action Creators 中修改参数对象
在 Action Creators 中,我们经常需要根据传入的参数对象生成 Action 对象。但有时我们会错误的直接修改参数对象,这样会破坏 React 应用的单向数据流,导致状态变得不可预测。
例如,下面的 Action Creators 中修改了传入的参数对象:
function addUser(user) { // 在 user 对象中添加一个 id 字段 user.id = Math.random().toString(16).slice(2) return { type: 'ADD_USER', payload: user } }
这种写法在添加用户时非常方便,但是它修改了传入的参数对象,可能会影响到其他组件,导致 React 应用的状态变得不可预测。
解决方案
为了避免修改参数对象,我们可以使用 Object.assign() 或者 Spread Operator 来创建新的对象,并将修改后的数据合并进去,这样可以保证 React 应用的单向数据流不被破坏。
例如,上面的 Action Creators 可以改写成这样:
function addUser(newUser) { const user = Object.assign({}, newUser, { id: Math.random().toString(16).slice(2) }) return { type: 'ADD_USER', payload: user } }
这种写法会创建一个新的 user 对象,而不会修改传入的参数对象。
陷阱 3:在 Action Creators 中包含业务逻辑
在 Action Creators 中,我们需要将应用的状态变更逻辑集中在一处,但是有时我们会被诱惑在其中加入业务逻辑,这样会让 Action Creators 可扩展性变差,可读性变差,导致代码难以维护。
例如,下面的 Action Creators 中包含了业务逻辑,它需要根据用户的余额和购买商品的价格来判断是否可以购买:
-- -------------------- ---- ------- -------- ---------------- -------- - ----- ---------- - ------------- - ---------------- -- ------------- - ----------- - ------ - ----- --------------------- -------- ------------- -------- - - ----- ------- - ----------------- ----- - -------- ------------ - ---------- -- ------ - ----- ---------------------- -------- - ----- -------- ------- - - -
这种写法看起来非常方便,但是它将判断是否购买商品的逻辑和应用的状态变更逻辑混为一体,导致这个 Action Creators 不够通用,也不够容易测试。
解决方案
为了避免在 Action Creators 中包含业务逻辑,我们应该将它们拆成多个不同的函数,每个函数都只负责一个特定的逻辑区域。这样可以提高代码的可读性、可扩展性以及可维护性。
例如,上面的 Action Creators 可以拆成三个函数:
-- -------------------- ---- ------- -------- ------------------- -------- - ----- ---------- - ------------- - ---------------- ------ ------------ -- ---------- - -------- ------------------- -------- - ----- ---------- - ------------- - ---------------- ------ ----------------- ----- - -------- ------------ - ---------- -- - -------- ---------------- -------- - -- --------------------- --------- - ------ - ----- --------------------- -------- ------------- -------- - - ----- ------- - ------------------- -------- ------ - ----- ---------------------- -------- - ----- -------- ------- - - -
这种写法将业务逻辑和状态变更逻辑拆分出来,每个函数只负责一个特定的逻辑。这不仅提高了代码的可读性和可维护性,还使 Action Creators 可以更容易地扩展和测试。
总结
Action Creators 是 Redux 中非常重要的一环,它们用来创建 Action 对象,将应用的状态变更逻辑集中在一处。然而,在实际开发中,我们经常会遇到一些 Action Creators 的陷阱,这篇文章介绍了这些陷阱的原因和解决方案,希望可以帮助您更好地理解 Redux 中的 Action Creators。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64e47032f6b2d6eab3fdf0aa