todoList案例(创建组件的2种方法:class和function)

React Hooks - TodoList

App.js

import React, { useState, useCallback,useEffect } from 'react';

// 导入组件
import TodoInput from './components/TodoInput';
import TodoList from './components/TodoList';

function App () {

  const [todoList, setTodoList] = useState([]);

  /**
   * 处理副作用 【重点】
   * 若第二个参数为空数组,则只执行一次
   * 若第二个参数有值,表示该值发送变化,执行一次
   */
  useEffect(()=>{
    let _todoList = JSON.parse(localStorage.getItem('todoList') || '[]');
    setTodoList(_todoList);
  },[])

  // 每当 todoList 变化,本地存储重新赋值 【重点】
  useEffect(() => {
    localStorage.setItem('todoList', JSON.stringify(todoList))
  }, [todoList])

  /**
   * 以属性的方法,将函数传递给子组件,使用 useCallback 包裹
   * 使用 useCallback 保证:属性不变时,子组件不会重新渲染
   * useCallback后面的[],是否依赖外部变量、方法
   */

  const addTodoItem = useCallback((todoItem) => {
    setTodoList(todoList => [todoItem, ...todoList])
  }, [])


  const setCompleted = useCallback((id) => {
   
    setTodoList(todoList => {
      return todoList.map(item => {
        if (item.id === id) {
          item.completed = !item.completed;
        }
        return item;
      })
    })
  }, [])

  const removeTodoItem = useCallback((id) => {
    setTodoList(todoList => {
      return todoList.filter((item) => {
        return item.id !== id;
      })
    })
  }, [])

  return (
    <div className="app">
      <TodoInput
        addTodoItem={addTodoItem}
      />
      <TodoList
        todoList={todoList}
        setCompleted={setCompleted}
        removeTodoItem={removeTodoItem}
      />
    </div>
  )
}

export default App;

src / components/TodoInput.js

import React, { useRef } from 'react';

function TodoInput(props){

  const inputRef = useRef(),
    { addTodoItem } = props;


  const addTodo = () => {
    const _val = inputRef.current.value.trim();

    if (_val.length === 0) {
      return;
    }

    addTodoItem({
      id: new Date().getTime(),
      content: _val,
      completed: false,
    })

    inputRef.current.value = "";

  }

  return (
    <div>
      <input
        type="text"
        ref={inputRef}
      />
      <button onClick={addTodo}>增加</button>
    </div>
  )
}

export default TodoInput;

src/components/TodoList.js

import React from 'react';

function TodoList (props) {

  const { todoList, setCompleted, removeTodoItem } = props;

  return (
    <ul>
      {
        todoList.map((item, index) => {
          return (
            <li key={index}>
              <input
                type="checkbox"
                checked={item.completed}
                onChange={() => setCompleted(item.id)}
              />
              <span
                style={{ textDecoration: item.completed ? 'line-through' : 'none' }}
              >{item.content}</span>
              <button onClick={() => removeTodoItem(item.id)}>删除</button>
            </li>
          )
        })
      }
    </ul>
  )
}

export default TodoList;

React class component - TodoList

App.js

import React, { Component } from 'react';

// 导入组件
import TodoInput from './components/TodoInput';
import TodoList from './components/TodoList';

class App extends Component {

  state = {
    todoList: []
  }

  // 方法
  addTodoItem (todoItem) {
    this.state.todoList.push(todoItem);
    this.setState({
      todoList: this.state.todoList
    })
  }

  setCompleted (id) {
    const todoList = this.state.todoList.map(item => {
      if (item.id === id) {
        item.completed = !item.completed;
      }
      return item;
    })
    this.setState({ todoList })
  }

  removeTodoItem (id) {
    const todoList = this.state.todoList.filter(item => item.id != id);
    this.setState({ todoList })
  }

  render () {
    return (
      <div className="app">
        <TodoInput
          addTodoItem={this.addTodoItem.bind(this)}
        />
        <TodoList
          todoList={this.state.todoList}
          setCompleted={this.setCompleted.bind(this)}
          removeTodoItem={this.removeTodoItem.bind(this)}
        />
      </div>
    )
  }

}

export default App;

src/components/TodoInput.js

import React, { Component } from 'react';

class TodoInput extends Component {

  state = {
    todoValue: ''
  }

  // 方法
  setTodoValue (e) {
    this.setState({
      todoValue: e.target.value
    })
  }

  addTodo () {
    const _val = this.state.todoValue.trim(),
      { addTodoItem } = this.props;

    if (_val.length === 0) {
      return;
    }

    addTodoItem({
      id: new Date().getTime(),
      content: _val,
      completed: false,
    })

    this.setState({
      todoValue: ""
    })

  }

  render () {

    const { todoValue } = this.state;

    return (
      <div>
        <input
          type="text"
          onChange={e => this.setTodoValue(e)}
          value={todoValue}
        />
        <button onClick={this.addTodo.bind(this)}>增加</button>
      </div>
    )
  }
}

export default TodoInput;

src/components/TodoList.js

import React, { Component } from 'react';

class TodoList extends Component {


  render () {


    const { todoList, setCompleted, removeTodoItem } = this.props;

    return (
      <ul>
        {
          todoList.map((item, index) => {
            return (
              <li key={index}>
                <input
                  type="checkbox"
                  checked={item.completed}
                  onChange={() => setCompleted(item.id)}
                />
                <span
                  style={{ textDecoration: item.completed ? 'line-through' : 'none' }}
                >{item.content}</span>
                <button onClick={()=>removeTodoItem(item.id)}>删除</button>
              </li>
            )
          })
        }
      </ul>
    )
  }
}

export default TodoList;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落花流雨

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值