react的状态管理简单钩子方法

1.recoil

useProvider文件:

import { atom, useRecoilState } from 'recoil';

const initState = atom({
    key: 'initState',
    default: {
        state: [],
    },
})

// 将业务逻辑拆分到一个单独文件中,方便进行状态管理
export interface StateProps {
    id: number;
    text: string;
    isFinished: boolean;
}
export interface ActionProps {
    type: string;
    [key: string]: any;
}
export const reducer = (state: StateProps[], action: ActionProps) => {
    console.log(state, action)
    switch (action.type) {
        case 'ADD':
            return [...state, action.todo];
        case 'CHANGESTATUS':
            return state.map(item => {
                if (item.id === action.id) {
                    return Object.assign({}, item, { isFinished: !item.isFinished })
                }
                return item;
            });
        default:
            return state;
    }
}

export const useProvider = () => {
    // 改变todo
    const [context, dispatch]: any = useRecoilState(initState);

    const changeTodo = (id: number) => {
        const todoList = reducer(context.state, { type: 'CHANGESTATUS', id: id })
        dispatch({ state: todoList });
    }
    // 添加todo
    const addTodo = (todo: StateProps) => {
        const todoList = reducer(context.state, { type: 'ADD', todo })
        dispatch({ state: todoList });
    }
    return { changeTodo, addTodo, todoList: context.state };
}

Todo组件:

import { TodoInput } from "./TodoInput";
import { TodoList } from "./TodoList";

// 父组件
export const Todo = () => {
    return (
        <>
            <TodoInput />
            <TodoList  />
        </>
    )
}

TodoInput组件:

import { useState } from "react";
import _ from 'lodash';
import { useProvider } from "./useProvider";


// 子组件
export const TodoInput = () => {
    const [text, setText] = useState('');
    const {addTodo} = useProvider();
    const handleChangeText = (e: React.ChangeEvent) => {
        setText((e.target as HTMLInputElement).value);
    }
    const handleAddTodo = () => {
        if (!text) return;
        addTodo({
            id: new Date().getTime(),
            text: text,
            isFinished: false,
        })
        setText('');
    }
    return (
        <div className="todo-input">
            <input type="text" placeholder="请输入代办事项" onChange={handleChangeText} value={text} />
            <button style={{ marginLeft: '10px' }} onClick={handleAddTodo} >+添加</button>
        </div>
    )
}

TodoItem组件:

import { useProvider } from "./useProvider";
import _ from 'lodash';

// 孙子组件
export const TodoItem = ({ todo }: {
    todo:any;
    key: any;
}) => {
    const {changeTodo} = useProvider();
    // 改变事项状态
    const handleChange = () => {
        changeTodo(_.get(todo, 'id'));
    }
    return (
        <div className="todo-item">
            <input type="checkbox" checked={todo.isFinished} onChange={handleChange} />
            <span style={{ textDecoration: todo.isFinished ? 'line-through' : 'none' }}>{todo.text}</span>
        </div>
    )
}

TodoList组件:

import { TodoItem } from "./TodoItem";
import { useProvider } from "./useProvider";
import _ from 'lodash';

export const TodoList = () => {
    const {todoList} = useProvider();
    return (
        <div className="todo-list">
            {_.map(todoList, item => <TodoItem key={_.get(item, 'id')} todo={item||{}} />)}
        </div>
    )
}

然后在App组件引入Todo组件<Todo />

import { RecoilRoot } from 'recoil';
import './App.css';
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import { Todo } from './recoilProvider/Todo';



const App:React.FC = ()=> {
  return (
    <RecoilRoot>
      <ErrorBoundary>
        <React.Suspense fallback={<div>Loading...</div>}>
          <div className='App'>
            <Todo />
          </div>
        </React.Suspense>
      </ErrorBoundary>
  </RecoilRoot>
  );
}

export default App;

2.context状态管理:

useProvider文件:

import { createContext, useContext } from "react";

// 将业务逻辑拆分到一个单独文件中,方便进行状态管理
export interface StateProps {
    id: number;
    text: string;
    isFinished: boolean;
}
export interface ActionProps {
    type: string;
    [key: string]: any;
}
export const reducer = (state: StateProps[], action: ActionProps) => {
    console.log(state, action)
    switch (action.type) {
        case 'ADD':
            return [...state, action.todo];
        case 'CHANGESTATUS':
            return state.map(item => {
                if (item.id === action.id) {
                    return Object.assign({}, item, { isFinished: !item.isFinished })
                }
                return item;
            });
        default:
            return state;
    }
}


export interface ContextProps {
    state: StateProps[];
    dispatch: React.Dispatch<ActionProps>;
}
// const MyContext = createContext<ContextProps | null>(null); // 泛型写法
export const MyContext = createContext({} as ContextProps); // 断言写法

export const useProvider = () => {
    // 改变todo
    const context = useContext(MyContext);
    const changeTodo = (id: number) => {
        context.dispatch({ type: 'CHANGESTATUS', id: id });
    }
    // 添加todo
    const addTodo = (todo: StateProps) => {
        context.dispatch({ type: 'ADD', todo });
    }
    return { changeTodo, addTodo, todoList: context.state, context };
}

ContextProvider文件:

import { useContext, useReducer } from "react";
import { MyContext, StateProps, reducer } from "./useProvider";


const ContextProvider = (props: React.PropsWithChildren<{}>) => {
    const context = useContext(MyContext);
    const initState: StateProps[] = context.state || [];
    const [state, dispatch] = useReducer(reducer, initState);

    return (
        <MyContext.Provider value={{ state, dispatch }} >
            {/* 插槽内容 */}
            {props.children}
        </MyContext.Provider>
    )
}

export default ContextProvider;

Todo组件:

import ContextProvider from "./ContextProvider";
import { TodoInput } from "./TodoInput";
import { TodoList } from "./TodoList";

// 父组件
export const Todo = () => {
    return (
        <ContextProvider>
            <TodoInput />
            <TodoList  />
        </ContextProvider>
    )
}

TodoInput 和TodoList 组件不变

使用Todo组件直接使用<Todo />就行;

效果图如下:

点击添加按钮,新增一列,点击多选框(选中)中划线一行,取消选中该行就恢复正常

相关推荐
cs_dn_Jie7 分钟前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic41 分钟前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿1 小时前
webWorker基本用法
前端·javascript·vue.js
清灵xmf2 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据2 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161772 小时前
防抖函数--应用场景及示例
前端·javascript
334554323 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test3 小时前
js下载excel示例demo
前端·javascript·excel
PleaSure乐事3 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶3 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json