基于函数组件+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 = ''
}
}
网友评论