React 怎么用组件实现一个简单的todo list?

Handle(添加组件)

import React, { Component } from 'react';

class Handle extends Component {

    state = {
        inputVal: ''
    }
    
    render(){
        let {inputVal} = this.state;
        return (
            <div className="handle">
                <input type="text" value={inputVal} onChange={this.changeAction}/>
                <button onClick={this.addAction}>添加</button>
            </div>
        );
    }

    changeAction = (ev)=>{
        this.setState({inputVal: ev.target.value});
    }

    // 添加数据
    addAction = ()=>{
        // 调用父组件的方法
        this.props.onAdd(this.state.inputVal);
        // 清空输入框
        this.setState({inputVal: ''});
    }

}

export default Handle;

List(列表组件)

import React, { Component } from 'react';

class List extends Component {
    render() {
        let { data } = this.props;
        return (
            <ul className="list">
            {
                data.map((item, index)=>(
                    <li finished')?'line-through':'none'}}>
                        <span>{item.value}</span>
                        {(item.status!=='finished') && <button onClick={()=>this.finishAction(index)}>完成</button>}
                        <button onClick={()=>this.deleteAction(index)}>删除</button>
                    </li>
                ))
            }
            </ul>
        );
    }

    // 每一项数据完成的点击事件
    finishAction = (index)=>{
        this.props.onFinishItem(index);
    }

    // 每一项数据的删除事件
    deleteAction(index){
        this.props.onDeleteItem(index);
    }
}

export default List;

Tools(选项组件)

import React, { Component } from 'react';

class Tools extends Component {
    render() {
        let btns = [
            {title: '所有', status: 'all'},
            {title: '完成', status: 'finished'},
            {title: '未完成', status: 'todo'}
        ]
        return (
            <ul className="tools">
            {
                btns.map(item=>{
                    return (
                        <li key={item.status} onClick={()=>this.changeStatusAction(item.status)}>
                            {item.title}
                        </li>
                    )
                })
            }
            </ul>
        );
    }

    changeStatusAction = (status)=>{
        this.props.onChangeStatus(status);
    }
}

export default Tools;

APP组件

import React, { Component } from 'react';
import Handle from './components/Handle'
import List from './components/List'
import Tools from './components/Tools'

class App extends Component {
    state = {
        data: [],
        status: 'all'
    };

    render() {
        let {data, status} = this.state;

        // 过滤数据
        let newData = data.filter((item,index)=>{
            if(status === 'all'){
                return true;
            }else{
                return item.status === status;
            }
        })

        return (
            <div >
                <Handle onAdd={this.handleAdd}/>
                <List data={newData} onFinishItem={this.handleFinishItem} onDeleteItem={this.handleDeleteItem}/>
                <Tools onChangeStatus={this.handleChangeStatus}/>
            </div>
        );
    }

    // 处理Handle组件添加的数据的事件
    handleAdd = (value)=>{
        let info = {
            value,
            status: 'todo'
        };
        this.setState({data: [...this.state.data, info]});
    }

    // 处理完成的事件
    handleFinishItem = (index)=>{
        // todo ---> finished
        let newArr = this.state.data.map((item, i)=>{
            if(index !== i){
                return item;
            }else{
                return {
                    ...item,
                    status: 'finished'
                }
            }
        })

        this.setState({data: newArr});
    }

    // 删除item
    handleDeleteItem = (index)=>{
        let newArr = this.state.data.filter((item, i)=>{
            return index !== i;
        });

        this.setState({data: newArr});

    }

    // 处理修改todolist需要展示每一项待办事件
    handleChangeStatus = (flag)=>{
        this.setState({ status: flag });
    }
}

export default App;