本文转载自:众成翻译
译者:iOSDevLog
链接:http://www.zcfy.cc/article/3825
原文:https://www.fullstackreact.com/30-days-of-react/day-20/
使用Redux,我们来谈谈我们如何在我们的应用中实际修改Redux状态。
昨天,我们经历了整合我们的反应应用与Redux的困难部分。从现在起,我们将使用我们的Redux设置来定义函数。
现在,我们的演示应用能显示当前时间。但目前还没有任何方法可以更新到新的时间。现在,让我们修改这个。
触发更新
回想一下,我们能在Redux中改变数据的唯一方法是通过一个动作创建者。昨天我们创建了一个Redux的store,但我们还没有为我们的store创造一个更新的方法。
我们 想要 的是我们的用户通过点击按钮来更新时间的能力。为了添加此函数,我们需要执行以下几个步骤:
创建一个 actionCreator 来 分发 我们store的动作
调用一个元素的 actionCreator "onClick"
处理归约器的动作
我们已经实现了第三个步骤,所以我们还有两件事要做,才能让这个函数像我们预期的那样工作。
昨天,我们讨论了什么是动作,但不是真正的为什么我们使用这个东西叫 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的完整功能。
[](#multi-reducers)多归约器
现在,我们我们的应用有一个单一的归约器。这是目前的工作,因为我们只有少量的简单数据和 (想必) 只有一个人在这个应用工作。试想一下,在我们的应用中为_每一片数据_开发一个巨大的开关语句。
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的能力来保存我们的数据。
今天的工作很好,明天见!
原文链接:https://www.f2er.com/react/303251.html