React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,如今就開始用 React+Redux 進行實戰!css
React 實踐項目 (一)html
本次實踐代碼前端
部署好的網址vue
應用中全部的 state 都以一個對象樹的形式儲存在一個單一的 store 中。
唯一改變 state 的辦法是觸發 action,一個描述發生什麼的對象。
爲了描述 action 如何改變 state 樹,你須要編寫 reducers。node
咱們接下來開始開始進行登錄與註冊的狀態管理react
首先在 src
目錄下建立 redux
文件夾,目錄以下git
digag ├── README.md ├── node_modules ├── package.json ├── .gitignore ├── public │ └── favicon.ico │ └── index.html │ └── manifest.json └── src └── components └── Index └── Header.js └── LoginDialog.js └── RegisterDialog.js └── containers └── App └── App.js └── App.css └── redux └── action └── users.js └── reducer └── auth.js └── users.js └── sagas └── api.js └── sagas.js └── selectors.js.js └── users.js └── store └── store.js └── App.test.js └── index.css └── index.js └── logo.svg └── registerServiceWorker.js
代碼可今後獲取github
記得在 package.json
中更新依賴json
action
action/users.jsredux
/* * action 類型 */ export const REGISTER_USER = 'REGISTER_USER'; // 省略其餘action 類型 /* * action 建立函數 */ export const registerAction = (newUser) => { return{ type:REGISTER_USER, data: newUser, } }; // 省略其餘 action 建立函數
reducer
reducer/users.js
//Immutable Data 就是一旦建立,就不能再被更改的數據。 //對 Immutable 對象的任何修改或添加刪除操做都會返回一個新的 Immutable 對象。 import Immutable from 'immutable'; //從 action 導入須要的 action 類型 import {REGISTER_USER, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE} from '../action/users'; // 初始化狀態 const initialState = Immutable.fromJS({ newUser: null, error: null, saveSuccess: false, }); // reducer 就是一個純函數,接收舊的 state 和 action,返回新的 state。 export const users = (state = initialState, action = {}) => { switch (action.type) { // 判斷 action 類型 case REGISTER_USER: return state.merge({ // 更新狀態 'newUser': action.data, 'saveSuccess': false, 'error': null, }); case REGISTER_USER_SUCCESS: return state.set('saveSuccess', action.data); case REGISTER_USER_FAILURE: return state.set('error', action.data); default: return state } };
store
store/store.js
import {createStore, combineReducers, applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux-saga' import * as reducer from '../reducer/users'; import rootSaga from '../sagas/sagas'; const sagaMiddleware = createSagaMiddleware(); const store = createStore( combineReducers(reducer), applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga); export default store;
store
src/index.js
import {Provider} from 'react-redux'; import store from './redux/store/store'; // 省略其餘 ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
import {registerAction, loginAction} from '../../redux/action/users'; import {connect} from "react-redux"; import {bindActionCreators} from "redux"; //省略其餘 class App extends Component { render(){ return( <div className="App"> //省略 </div> ) } } export default connect( (state) => { // 獲取狀態 state.users 是指 reducer/users.js 文件中導出的 users // 能夠 `console.log(state);` 查看狀態樹 return { users: state.users } }, (dispatch) => { return { // 建立action registerActions: bindActionCreators(registerAction, dispatch), loginActions: bindActionCreators(loginAction, dispatch), } })(App); // 在App 組件的props裏就有 this.props.users this.props.registerActions this.props.loginActions 了 // 須要注意的是這裏this.props.users是Immutable 對象,取值須要用this.props.users.get('newUser') // 也可在 reducer 裏改用 js 普通對象
裝飾器版本:
須要在Babel中開啓裝飾器
裝飾器插件babel-plugin-transform-decorators-legacy
@connect( (state) => { console.log(state); return ({ users: state.users, }); }, {registerActions: registerAction, loginActions: loginAction} )
registerActions
傳給RegisterDialog子組件,src/components/Index/RegisterDialog.js
// 省略其餘代碼 handleSubmit = (e) => { e.preventDefault(); // 驗證表單數據 this.refs.user.validate((valid) => { if (valid) { // this.state.user 爲表單收集的 用戶註冊數據 this.props.registerActions(this.state.user); this.setState({loading: true}); } }); };
調用 action
`this.props.registerActions(this.state.user);` 返回action 爲
{ type:REGISTER_USER, data: this.state.user, }
reducer 根據action類型更新狀態
switch (action.type) { case REGISTER_USER: return state.merge({ 'newUser': action.data, 'saveSuccess': false, 'error': null, }); //省略其餘代碼
這時咱們的store裏的狀態 newUser
就被更新爲 註冊彈窗裏收集的數據
到這裏都仍是同步的action,而註冊是一個異步的操做。
下篇文章會介紹如何使用 redux-saga 進行異步操做。
redux-saga 已經在使用了,有興趣的能夠自行查看代碼理解。
記得點star:)
項目代碼地址:https://github.com/DigAg/diga...
vue2版項目代碼地址:https://github.com/DigAg/diga...
相應後端項目代碼地址:https://github.com/DigAg/diga...