基于函數組件+redux+react-redux完成todolist的demo
demo地址:
https://github.com/jc5055/react-redux-hook
知識點:
函數組件:
useState
:定義組件當前的state的屬性
//isShowDelBtn:定義變量,初始值為false,作用域為當前組件
//setIsShowDelBtn:更新變量isShowDelBtn,作用域為當前組件
const [isShowDelBtn, setIsShowDelBtn] = useState(false)
//更新isShowDelBtn變量
setIsShowDelBtn(true)
useEffect
:副作用函數,useEffect(()=>{ return }, par2)
通過par2參數的設置實現類組件函數中的狀態如‘ componentWillMount’,‘ componentDidUnmount’,‘ componentWillUpdate’
useEffect(()=>{
dispatch({
type:actionType.GET_ALL_TODO
})
}, [dispatch])
useCallback
: 用useCallback
定義的回調函數,傳遞給子組件,配合子組件的memo
定義,減少不必要的組件刷新,與useEffect
類似
useRef
:組件內獲取控件的輸入
//Top.js
//組件函數內聲明
const inputRef = useRef()
//input 標簽賦值
<input type="text"
placeholder="請輸入今天的任務清單,按回車鍵確認"
onKeyDown={(event)=>{_handleKeyEvent(event)}}
ref={inputRef}
/>
//獲取值
const value = inputRef.current.value
redux:
使用redux
目的是解決組件樹深度過大,屬性需要依次傳遞,代碼閱讀性和維護性差的問題。使用redux
基本要素:
大堂經理根據用戶需求判斷具體的業務類型
銀行柜員更具業務類型,執行具體的操作,從而實現用戶賬戶的更新
- 1.
store
(銀行數據庫):類似數據庫用來存儲數據,數據只能被reducer
訪問, - 2.
reducer
(銀行柜員):具體行為的操作,根據行為類型去執行具體操作,從而實現store
里面的數據更新 - 3.
actionType
(大堂經理):具體代表類型
代碼實現:
步驟一:定義行為類型actionType
//actionType.js
// 1. 存所有的Todo
const GET_ALL_TODO = 'get_all_todo'
export default {
GET_ALL_TODO,
}
步驟二:定義行為操作reducer
reducer
的基本形式為(state, action)=>{return state}
,
state
為對應reducer
所控store
里面的數據;
action
為具體行為,包括行為類型action.type
, 行為參數action.payload
為了代碼可讀性,使用combineReducers
對不通的reducer進行合并成一個reducer,賦值給store
import {combineReducers} from 'redux'
import todoReducer from './todoReducer'
export const reducer = combineReducers({
todoReducer : todoReducer
})
步驟三:定義store
將reducer賦值給store,完成store的新建
import {createStore} from 'redux'
import {reducer} from "./reducer/index"
const store = createStore(reducer)
export default store
至此完成了redux的基礎的定義:actionType, reducer, store
react-redux:
知識點一:Provider標簽
import react-redux
,在index.js
文件用Provider
標簽對App
標簽包裹,使得App
下的組件都能獲取store
的值
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {Provider} from 'react-redux'
import store from "./store/store";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
知識點二:useSelector
在子組件中import react-redux
的API useSelector
可以獲取sotre對應的數據。
考慮到使用combineReducers
的將不通的reducer
進行合并,因此要獲取特定reducer
設定的store
數據,需要加上對應的reducer
key如下文
//index.js 在此文件將不通的reudcer進行統一
import {combineReducers} from 'redux'
import todoReducer from './todoReducer'
export const reducer = combineReducers({
todoReducer : todoReducer
})
//Top.js在此文件獲取todoReducer下聲明的store的數據
import {useSelector, useDispatch} from 'react-redux'
const todos = useSelector(state => state.todoReducer.todos)
知識點三:useDispatch
useDispatch的作用是在子組件中,可以觸發對應的reducer的行為操作,進而實現對store的數據更新。具體操作步驟
- 1.
import {useDispatch}from 'react-redux'
- 2.在函數組件中定義對象
const dispatch = useDispatch()
- 3.
dispatch((type,payload))
的方式傳遞行為類型和行為所需要的參數 - 4.
react-redux
會監聽行為,改變store
存儲的數據
//App.js
import {useSelector, useDispatch} from 'react-redux'
useEffect(()=>{
dispatch({
type:actionType.GET_ALL_TODO
})
}, [dispatch])
// Top.js
const dispatch = useDispatch()
const _handleKeyEvent = (e)=>{
const lastTodoId = todos.length === 0 ? 0: todos[todos.length - 1].id
if (13 === e.keyCode){
const value = inputRef.current.value
if (!value.trim()){
alert('輸入的內容不為空')
return
}
const todo = {id:lastTodoId, title:value, finished:false}
dispatch({
type: actionType.ADD_ONE_TODO,
payload: todo
})
inputRef.current.value = ''
}
}