安裝
yarn add redux
或者
npm install --save-dev redux
// /src/store/actionCreators.js
import { CHANGINPUT, ADDBBIMN, DELEMTITEM } from './actionTypes'
export const changInput = (value) => ({
type: CHANGINPUT,
value: value
})
export const addbindCheng = () => ({
type: ADDBBIMN,
})
export const deleteItemCheng = (index) => ({
type: DELEMTITEM,
value:index
})
// /src/store/actionTypes.js
export const CHANGINPUT = 'CHANGINPUT'
export const ADDBBIMN = 'Add_bbimn'
export const DELEMTITEM = 'DelemtItem'
// /src/store/
// /src/store/index.js
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store
// /src/store/reducer.js
import { CHANGINPUT, ADDBBIMN, DELEMTITEM } from './actionTypes'
const defaultStatus = {
inputValue: '這是屬性',
list: [
'1121',
'22222',
'33333',
'44444',
'55555'
]
}
//Reducer 必須是純函數 不能調用ajax 等等
export default (state = defaultStatus, action) => {
console.log(state, action)
if(action.type === CHANGINPUT) {
// Reducer 裏只能接受 state 不能改變state
let newStade = JSON.parse(JSON.stringify(state))
newStade.inputValue = action.value
return newStade
}
if (action.type === ADDBBIMN) {
let newStade = JSON.parse(JSON.stringify(state))
newStade.list.push(newStade.inputValue)
return newStade
}
if(action.type === DELEMTITEM) {
let newStade = JSON.parse(JSON.stringify(state))
newStade.list.splice(action.value, 1)
return newStade
}
return state
}
// /src/TodoList.jsx
import React, { Component } from 'react'
import store from './store'
import { CHANGINPUT, ADDBBIMN, DELEMTITEM } from './store/actionTypes'
import { changInput, addbindCheng, deleteItemCheng} from './store/actionCreators'
import TodoListUI from './TodoListUI'
import axios from 'axios'
export default class TodoList extends Component {
constructor(props){
super(props)
console.log(store.getState()) // 輸入值
this.state = store.getState()
this.storeChange = this.storeChange.bind(this)
// 如果不加這個 綁定value(有坑)value 數據不會發生變化
store.subscribe(this.storeChange)
this.addbind = this.addbind.bind(this)
this.deleteItem = this.deleteItem.bind(this)
}
componentDidMount() {
axios.get('http://mock-api.com/jzAV0Ggk.mock/Updeat').then((datas) => {
// JSON.parse(data.data)
console.log(datas.data)
})
}
changeOn(e) {
// console.log(e.target.value)
const action = changInput(e.target.value)
store.dispatch(action)
}
storeChange(){
this.setState(store.getState())
}
addbind() {
const action = addbindCheng()
store.dispatch(action)
}
deleteItem(index) {
console.log(index)
// const action = {
// type: DELEMTITEM,
// value: index
// }
const action = deleteItemCheng(index)
store.dispatch(action)
}
render() {
return (
<TodoListUI
inputValue= {this.state.inputValue}
addbind= {this.addbind}
list = { this.state.list }
deleteItem={this.deleteItem}
/>
)
}
}
// /src/TodoListUI.jsx
import React, { Component } from 'react'
import { Button, Input, List } from 'antd';
// UI 改成無狀態組件性能更高
const TodoListUI = (props) => {
return (
<div style={{marginLeft:'20px',marginTop:'20px'}}>
<div>
<Input placeholder="請選擇" value={props.inputValue} style={{width:'250px'}} onChange={props.changeOn}></Input>
<Button type="primary" style={{marginLeft:'20px'}} onClick={props.addbind}>增加</Button>
</div>
<div style={{width:'300px'}}>
<List
bordered
dataSource={props.list}
renderItem={(item, index)=>(<List.Item onClick={() => props.deleteItem(index)}>{item}</List.Item>)}
/>
</div>
</div>
)
}
/* class TodoListUI extends Component {
render() {
return (
<div style={{marginLeft:'20px',marginTop:'20px'}}>
<div>
<Input placeholder="請選擇" value={this.props.inputValue} style={{width:'250px'}} onChange={this.props.changeOn}></Input>
<Button type="primary" style={{marginLeft:'20px'}} onClick={this.props.addbind}>增加</Button>
</div>
<div style={{width:'300px'}}>
<List
bordered
dataSource={this.props.list}
renderItem={(item, index)=>(<List.Item onClick={(index) => { this.props.deleteItem(index)}}>{item}</List.Item>)}
/>
</div>
</div>
)
}
} */
export default TodoListUI;
使用中間件 redux-thun
安裝
yarn add redux-thun
改變 src/store/index.js
/**
* compose 增強函數
*/
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
const enhancer = composeEnhancers(applyMiddleware(thunk))
const store = createStore(reducer,enhancer)
export default store
// 改變 src/store/actionCreators.js
import { CHANGINPUT, ADDBBIMN, DELEMTITEM, GETLIST} from './actionTypes'
import axios from 'axios'
export const changInput = (value) => ({
type: CHANGINPUT,
value: value
})
export const addbindCheng = () => ({
type: ADDBBIMN,
})
export const deleteItemCheng = (index) => ({
type: DELEMTITEM,
value:index
})
export const getlistAction = (data) =>({
type: GETLIST,
value: data
})
// 安裝了 redux-thun 纔可以調用 axios
export const ListGet = () =>{
return (dispatch) =>{
axios.get('http://mock-api.com/jzAV0Ggk.mock/Updeat').then(res=>{
const data = res.data.split(',')
const action = getlistAction(data)
dispatch(action)
})
}
}
// // /src/TodoList.jsx 修改
import React, { Component } from 'react'
import store from './store'
import { changInput, addbindCheng, deleteItemCheng, ListGet} from './store/actionCreators'
import TodoListUI from './TodoListUI'
export default class TodoList extends Component {
constructor(props){
super(props)
console.log(store.getState()) // 輸入值
this.state = store.getState()
this.storeChange = this.storeChange.bind(this)
// 如果不加這個 綁定value(有坑)value 數據不會發生變化
store.subscribe(this.storeChange)
this.addbind = this.addbind.bind(this)
this.deleteItem = this.deleteItem.bind(this)
}
componentDidMount() {
// 如果沒有安裝 redux-thun 執行這句會報錯
const action = ListGet()
store.dispatch(action)
}
changeOn(e) {
console.log(e.target.value)
const action = changInput(e.target.value)
store.dispatch(action)
}
storeChange(){
this.setState(store.getState())
}
addbind() {
const action = addbindCheng()
store.dispatch(action)
}
deleteItem(index) {
console.log(index)
// const action = {
// type: DELEMTITEM,
// value: index
// }
const action = deleteItemCheng(index)
store.dispatch(action)
}
render() {
return (
<TodoListUI
inputValue= {this.state.inputValue}
changeOn = {this.changeOn}
addbind= {this.addbind}
list = { this.state.list }
deleteItem={this.deleteItem}
/>
)
}
}
// /src/store/reducer.js 修改
import { CHANGINPUT, ADDBBIMN, DELEMTITEM, GETLIST } from './actionTypes'
const defaultStatus = {
inputValue: '這是屬性',
list: [
'1121',
'22222',
'33333',
'44444',
'55555'
]
}
//Reducer 必須是純函數 不能調用ajax 等等
export default (state = defaultStatus, action) => {
console.log(state, action)
if(action.type === CHANGINPUT) {
// Reducer 裏只能接受 state 不能改變state
let newStade = JSON.parse(JSON.stringify(state))
newStade.inputValue = action.value
return newStade
}
if (action.type === ADDBBIMN) {
let newStade = JSON.parse(JSON.stringify(state))
newStade.list.push(newStade.inputValue)
return newStade
}
if(action.type === DELEMTITEM) {
let newStade = JSON.parse(JSON.stringify(state))
newStade.list.splice(action.value, 1)
return newStade
}
if (action.type === GETLIST) {
let newStade = JSON.parse(JSON.stringify(state))
newStade.list.push(action.value)
return newStade
}
return state
}
// /src/store//actionTypes.js 修改
export const CHANGINPUT = 'CHANGINPUT'
export const ADDBBIMN = 'Add_bbimn'
export const DELEMTITEM = 'DelemtItem'
export const GETLIST = 'GETLIST'
安裝 redux-saga
redux-saga 是redux的中間件 表示react的中間件
yarn add redux-saga
react-redux
安裝 必須安裝redux
yarn add redux react-redux
react-redux 例子
創建文件
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
src/App.js
import React, { Component } from 'react'
import {connect} from 'react-redux'
class App extends Component {
render() {
return (
<div>
<input value={this.props.inputValue} onChange={this.props.changClick}/>
<ul>
{this.props.list.map((item,index)=>{
return <li key={index} onClick={() => this.props.TonkOnClickDelete(index)}>{item}</li>
})}
</ul>
<button onClick={this.props.tjiaoOclick}>提交</button>
</div>
)
}
}
const mapStateToProps = (state, ownProps) => {
return {
inputValue: state.inputValue,
list: state.list
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
changClick(e) {
let action = {
type: 'CRLIOKD',
value: e.target.value
}
dispatch(action)
},
tjiaoOclick() {
let action = {
type: 'tjiaoOclick',
}
dispatch(action)
},
TonkOnClickDelete(index){
let action = {
type: 'Deletyes',
value: index
}
dispatch(action)
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(App)
src/store/index.js
import { createStore } from 'redux'
import reducer from './reducer'
const actions = createStore(reducer)
export default actions
src/store/reducer.js
const defaultstate = {
inputValue: '測試數據',
list: ['212121']
}
export default (state = defaultstate, action) => {
if(action.type === 'CRLIOKD') {
let newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if (action.type === 'tjiaoOclick') {
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
if(action.type === 'Deletyes') {
let newState = JSON.parse(JSON.stringify(state))
console.log(newState);
newState.list.splice(action.value,1)
return newState
}
return state
}