本文转载自:众成翻译
译者:iOSDevLog
连接:http://www.zcfy.cc/article/3825
原文:https://www.fullstackreact.com/30-days-of-react/day-20/react
使用Redux,咱们来谈谈咱们如何在咱们的应用中实际修改Redux状态。redux
昨天, 咱们经历了整合咱们的反应应用与Redux的困难部分。从如今起, 咱们将使用咱们的Redux设置来定义函数。异步
如今, 咱们的演示应用能显示当前时间。但目前尚未任何方法能够更新到新的时间。如今, 让咱们修改这个。socket
回想一下, 咱们能在Redux中改变数据的惟一方法是经过一个动做建立者。昨天咱们建立了一个Redux的store, 但咱们尚未为咱们的store创造一个更新的方法。函数
咱们 想要 的是咱们的用户经过点击按钮来更新时间的能力。为了添加此函数, 咱们须要执行如下几个步骤:学习
建立一个 actionCreator 来 分发 咱们store的动做测试
调用一个元素的 actionCreator "onClick"fetch
处理归约器的动做spa
咱们已经实现了第三个步骤, 因此咱们还有两件事要作, 才能让这个函数像咱们预期的那样工做。翻译
昨天, 咱们讨论了什么是动做, 但不是真正的为何咱们使用这个东西叫 actionCreators 或他们是什么。
做为复习, 动做是一个_必须_ 包含type
值简单的对象,。咱们建立了一个types.js
文件, 它保存在动做类型常量上, 所以咱们能够将这些值用做type
属性。
export const FETCH_NEW_TIME = 'FETCH_NEW_TIME';
做为快速审阅, 咱们的动做能够是具备type
键的任何对象值。咱们能够与咱们的行动一块儿发送数据 (一般, 咱们将把额外的数据做为一个动做的 payload 有效载荷
来传递)。
{ type: types.FETCH_NEW_TIME, payload: new Date().toString() }
如今, 咱们须要在咱们的store
_分发_。咱们能够这样作的一个方法就是调用store.dispatch()
函数。
store.dispatch({ type: types.FETCH_NEW_TIME, payload: new Date().toString() })
然而, 这是至关糟糕的作法。咱们将使用一个函数来返回一个动做, 而不是直接发送该动做, 该函数将 建立 该动做 (所以名称: actionCreator)。这为咱们提供了一个更好的测试故事 (易于测试)、可重用性、文档化和逻辑封装。
让咱们在一个名为redux/actionCreators.js
的文件中建立咱们的第一个actionCreator
。咱们将导出所有责任是返回一个适当的动做的一个函数, 以分发咱们的store。
import * as types from './types'; export const fetchNewTime = () => ({ type: types.FETCH_NEW_TIME, payload: new Date().toString(), }) export const login = (user) => ({ type: types.LOGIN, payload: user }) export const logout = () => ({ type: types.LOGOUT, })
如今, 若是咱们调用这个函数, 什么都不会发生 , 除了返回一个动做对象。咱们怎样才能让这个动做在store里分发?
It gets called with the dispatch
function, so here we can bind the function to call dispatch()
on the store.回想一下, 咱们昨天使用了 connect()
函数导出从react-redux
?第一个参数称为mapStateToProps
, 它将状态映射到一个属性对象。connect()
函数接受第二个参数, 这使得咱们也能够将函数映射到属性。它被调用的dispatch()
函数, 因此在这里咱们能够 绑定 函数以便在store调用dispatch()
。
让咱们来看看这个动做。在咱们的src/views/Home/Home.js
文件中, 让咱们经过提供第二个函数来更新咱们的链接, 以使用咱们刚刚建立的 actionCreator。咱们将调用mapDispatchToProps
这个函数。
import { fetchNewTime } from '../../redux/actionCreators'; // ... const mapDispatchToProps = dispatch => ({ updateTime: () => dispatch(fetchNewTime()) }) // ... export default connect( mapStateToProps, mapDispatchToProps, )(Home);
如今, updateTime()
函数将做为属性传递, 并将调用dispatch()
当咱们开始行动。让咱们更新咱们的 <Home />
组件, 以便用户能够按下一个按钮来更新时间。
const Home = (props) => { return ( <div className="home"> <h1>Welcome home!</h1> <p>Current time: {props.currentTime}</p> <button onClick={props.updateTime}> Update time </button> </div> ); }
虽然这个例子并不使人兴奋, 但它确实展现了Redux的特色。想象一下, 若是按钮获取新的鸣叫或咱们有一个socket驱动更新到咱们的Redux store。这个基本示例演示了Redux的完整功能。
如今, 咱们咱们的应用有一个单一的归约器。这是目前的工做, 由于咱们只有少许的简单数据和 (想必) 只有一我的在这个应用工做。试想一下, 在咱们的应用中为_每一片数据_开发一个巨大的开关语句。
Ahhhhhhhhhhhhhh...
Redux去营救!Redux有一种方法, 咱们把咱们的Redux归约器分红多个归约器, 每一个都只负责状态树的叶子。
咱们能够从 redux
使用combineReducers()
导出, 以组成一个对象的归约器函数。对于每一个触发的动做, 将使用相应的动做调用每一个函数。让咱们来看看这个动做。
假设咱们 (也许更现实一些) 想跟踪当前用户。让咱们建立一个currentUser
Redux模块..。您猜到了: src/redux/currentUser.js`:
touch src/redux/currentUser.js
咱们将导出咱们从currentTime
模块导出的相同的四个值...... 固然, 这一次是针对 currentUser 的。咱们在这里添加了一个基本的结构来处理当前用户:
import * as types from './types' export const initialState = { user: {}, loggedIn: false } export const reducer = (state = initialState, action) => { switch (action.type) { case types.LOGIN: return { ...state, user: action.payload, loggedIn: true}; case types.LOGOUT: return { ...state, user: {}, loggedIn: false}; default: return state; } }
让咱们更新咱们的configureStore()
函数来考虑这些分支, 使用combineReducers
将两个分支分开
import { createStore, combineReducers } from 'redux'; import { rootReducer, initialState } from './reducers' import { reducer, initialState as userInitialState } from './currentUser' export const configureStore = () => { const store = createStore( combineReducers({ time: rootReducer, user: reducer }), // root reducer { time: initialState, user: userInitialState }, // our initialState ); return store; } export default configureStore;
如今, 咱们能够建立login()
和logout()
动做创造者在咱们的store发送动做。
export const login = (user) => ({ type: types.LOGIN, payload: user }) // ... export const logout = () => ({ type: types.LOGOUT, })
如今, 咱们能够使用 actionCreators 像updateTime()
动做创造者同样调用login
和 logout
。
哦!这是Redux代码的又一个沉重的一天。今天, 咱们完成了数据更新和在全局Redux状态中存储数据之间的循环。此外, 咱们还学习了如何扩展Redux以使用多个归约器和动做以及多个链接的组件。
可是, 咱们尚未对站外数据进行异步调用。明天咱们将进入如何使用中间件与Redux, 这将使咱们可以处理从咱们的应用中获取远程数据, 仍然使用Redux的能力来保存咱们的数据。
今天的工做很好, 明天见!