Redux是什麼
- Redux專注於狀態管理,和react解耦 單
- 一狀態,單向數據流
- 核心概念:store,state,action,reducer
import { createStore } from 'redux'
const store = createStore(counter) // 創建倉庫
store.subscribe(listener) // 訂閱
store.dispatch({type: 'add'}) // 派發事件
store.dispatch({type: 'del'})
function counter (state=0, action) {
switch (action.type) {
case 'add':
return state+1
case 'del':
return state-1
default:
return 10
}
}
function listener () {
const current = store.getState()
console.log(current)
}
Redux狀態管理,使用React-redux
yarn add react-redux
React-redux提供Provide和connect兩個接口接口來鏈接
React-redux具體使用
- Provide組件在應用最外層,傳入store即可,只用一次
- Connect負責從外部獲取組件需要的參數
- Connect可以用裝飾器的方式來寫
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import thunk from 'redux-thunk'
import {createStore, applyMiddleware, compose} from 'redux'
import App from './App.js'
import { Provider } from 'react-redux'
import { counter } from './index.redux.js'
const reduxDevtools = window.devToolsExtension ? window.devToolsExtension() : () => {}
const store = createStore(counter, compose(
applyMiddleware(thunk),
reduxDevtools
))
ReactDOM.render(
(<Provider store={store}>
<App />
</Provider>)
, document.getElementById('root')
)
App.js
import React from 'react'
import { connect } from 'react-redux'
import { addGun, delGun, addGunAsync } from './index.redux.js'
class App extends React.Component{
render () {
return (
<div>
<h1>現在有激情{this.props.num}</h1>
<button onClick={() => this.props.addGun()}>申請武器</button>
<button onClick={() => this.props.delGun()}>放棄武器</button>
<button onClick={() => this.props.addGunAsync()}>拖兩天再給</button>
</div>
)
}
}
const mapStatetoProps = (state) => {
return {
num: state
}
}
const actionCreators = { addGun, delGun, addGunAsync }
App = connect(mapStatetoProps, actionCreators)(App)
export default App
index.redux.js
const ADD = 'add'
const DEL= 'del'
// reducer
export function counter (state=0, action) {
switch (action.type) {
case ADD:
return state+1
case DEL:
return state-1
default:
return 10
}
}
export function addGun () {
return {
type: ADD
}
}
export function delGun () {
return {
type: DEL
}
}
// 異步提交
export function addGunAsync () {
return dispatch => {
setTimeout(() => {
dispatch(addGun())
}, 2000)
}
}
使用裝飾器優化connect代碼
yarn eject 彈出個性化配置
yarn add @babel/plugin-proposal-decorators --dev 插件
Package.json裏babel加上plugins配置
["@babel/plugin-proposal-decorators", { “legacy”: true }]
"babel": {
"presets": [
"react-app"
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
App.js
// import React from 'react';
// import logo from './logo.svg';
// import './App.css';
// function App() {
// return (
// <div className="App">
// <header className="App-header">
// <img src={logo} className="App-logo" alt="logo" />
// <p>
// Edit <code>src/App.js</code> and save to reload.
// </p>
// <a
// className="App-link"
// href="https://reactjs.org"
// target="_blank"
// rel="noopener noreferrer"
// >
// Learn React
// </a>
// </header>
// </div>
// );
// }
// export default App;
// import React from 'react';
// import {Button} from 'antd-mobile'
// import 'antd-mobile/dist/antd-mobile.css'
// import { List } from 'antd-mobile';
// const Item = List.Item;
// class App extends React.Component{
// render () {
// let boss = '李雲龍'
// return (
// <div>
// <Yiying big='張大喵'></Yiying>
// <Qibinglian big='孫德勝'></Qibinglian>
// <h2>獨立團,團長{boss}</h2>
// </div>
// )
// }
// }
// function Qibinglian (props) {
// return <h2>騎兵連連長,{props.big}衝啊</h2>
// }
// class Yiying extends React.Component{
// constructor(props) {
// super(props)
// this.state = {
// solders: ['虎子', '柱子', '王根生']
// }
// // this.addSolder = this.addSolder.bind(this)
// }
// componentWillMount () {
// console.log('組件馬上就要加載了')
// }
// addSolder () {
// console.log('add solder')
// this.setState({
// solders: [...this.state.solders, '牛愛花' + Math.random()]
// })
// }
// componentDidMount () {
// console.log('組件加載完畢')
// }
// render () {
// console.log('組件正在加載了')
// return (
// <div>
// <h2>一營營長,{this.props.big}</h2>
// <Button type="primary" onClick={() => this.addSolder()}>新兵入伍</Button>
// <List renderHeader={() => '士兵列表'} className="my-list">
// {
// this.state.solders.map((item) => {
// return <Item arrow={'horizontal'} key={item}>{item}</Item>
// })
// }
// </List>
// </div>
// )
// }
// }
// export default App
import React from 'react'
import { connect } from 'react-redux'
import { addGun, delGun, addGunAsync } from './index.redux.js'
const actionCreators = { addGun, delGun, addGunAsync }
// App = connect(mapStatetoProps, actionCreators)(App)
@connect(
state => state.num, // 你要state什麼屬性放到props裏
{ addGun, delGun, addGunAsync } // 你要什麼方法,放到propsli ,自動dispatch
)
class App extends React.Component{
render () {
return (
<div>
<h1>現在有激情{this.props.num}</h1>
<button onClick={() => this.props.addGun()}>申請武器</button>
<button onClick={() => this.props.delGun()}>放棄武器</button>
<button onClick={() => this.props.addGunAsync()}>拖兩天再給</button>
</div>
)
}
}
export default App
後續進階:
- 什麼數據應該放在React裏
- Redux管理ajax
- Redux管理聊天數據