React实现一个TodoList | 青训营

92 阅读1分钟

实现TodoList(简易版)

今天用react实现一个todolist!
首先将整个功能拆分为四个组件,Header、List、Item、Footer。 它的目录结构如下:

image.png

APP.tsx

整体功能都放在这里,在这里进行list的状态管理。

注意,传过去的变量需要用useState进行状态管理,否则会出现检测不到变量变化的bug的!

注意更新list时可以使用map来更新状态

  const updateItem = (id: string, checked: boolean) => {
    let newList = list.map(item => {
      if (item.id === id) return { ...item, checked };
      else return item;
    });
    setList(newList);
  }

Header.tsx

输入框,用于增添Item。
通过接收App.tsx中传过来的addItem来进行对list的添加。

export default function Header(props: Props) {
    const { addItem } = props;
    const [val,setVal] = useState('');

    function handleKeyUp(e: any) {
        if (e.key == 'Enter') {
            addItem(val);
        }
    }
    function handleChange(e: any) {
        console.log(e.target.value);
        setVal(e.target.value);
    }
    return (
        <>
            <input type="text" placeholder='请输入待办事项,回车确认' onKeyUp={handleKeyUp} onChange={debounce(handleChange,0)} />
        </>
    )
}

List.tsx

存放Item

<div className='container'>
    {
        list.map((item:TItem) => {
            return <Item key={item.id} value={item.value}/>
        })
    }
</div>

这里写了发现没渲染上去,检查了半天发现是没在map里写return😭 (记得key也要写~)
简化了一下不写return的方式

list.map((item:TItem) => <Item key={item.id} value={item.value}/>)

Item.tsx

用于展示单个的item内容。

注意这里的handleCheck形式。

    const handleCheck = (id: string) => {
        return (e:any) => {
            updateItem(id,e.target.checked);
        }
    }
<input type="checkbox" checked={checked} onChange={handleCheck(id)} name="" id="" />

Footer.tsx

显示底部已完成/全部的数量,可以全选或全不选。

已完成的数量的变化,可以在App.jsx中通过useEffect来监测

  useEffect(() => {
    let n = 0;
    list.forEach(item => {
      if (item.checked) ++n;
    })
    setNum(n);
  }, [list])

也可以直接在Footer.jsx来计算已完成数量

//已完成的个数
const num = list.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0);

全选check的判断可以用下面这种方式

<input type="checkbox" checked={num === sum && sum !== 0} onChange={handleChange} name="" id="" />

整体样式: image.png