将类组件转换为功能组件时遇到问题

时间:2020-11-11 14:53:32

标签: javascript reactjs functional-programming react-hooks

我正在制作一个待办事项应用程序,并且通过将类组件变成功能组件来继续提高自己。 我使todo应用程序中最重要的位置(添加,删除)起作用,但是在转换为其他组件时遇到了问题。如果您可以检查和提供帮助,我们将不胜感激。

从类到功能

class App extends Component {
    state = {
      todos: []
    };

const App = () => {
  const [todos, setTodos] = useState([]);


ComponentDidMount以使用效果

  componentDidMount() {
    axios
      .get("https://jsonplaceholder.typicode.com/todos?_limit=10")
      .then((res) =>
        this.setState({
          todos: res.data
        })
      )
  }

useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/todos?_limit=10")
      .then((res) =>
        setTodos({
          todos: res.data // i'm not sure about here.
        })
      )
  }

将AddTodo分级为Func AddTodo

  
  Addtodo = (title) => {
    axios
      .post("https://jsonplaceholder.typicode.com/todos?", {
        title,
        completed: false
      })
      .then((res) =>
        this.setState({
          todos: [...this.state.todos, res.data]
        })
      )
  }

  const Addtodo = (title) => {
    axios.post("https://jsonplaceholder.typicode.com/todos", {
      title, 
      completed:false
    }).then((res) => setTodos({
      todos: [...todos, res.data] // I'm not sure about here.
    }))
  }

将DeleteTodo分级为Func Deletetodo

deleteTodo = (id) => {
    axios
      .delete(`https://jsonplaceholder.typicode.com/todos/${id}`)
      .then((res) =>
        this.setState({
          todos: [...this.state.todos.filter((todo) => todo.id !== id)]
        })
      )
  }

  const deleteTodo = (id) => {
    axios.delete(`https://jsonplaceholder.typicode.com/todos/${id}`)
    .then((res) => setTodos({
      todos:[...todos.filter((todo) => todo.id !== id)] // not sure
    }))
  }

将类别对勾标记标记为功能对勾标记

  markComplete = (id) => {
    this.setState({
      todos: this.state.todos.map((todo) => {
        if (todo.id === id) {
          todo.completed = !todo.completed
        }
        return todo
      })
    })
  }

  const markComplete = (id) => {
    setTodos({
      todos: todos.map((todo) => {
        if (todo.id === id) {
          todo.completed = !todo.completed
        }
        return todo
      })
    })
  }

最后一节,我希望我能正确理解道具。

<Addtodo Addtodo={() => Addtodo()} />

<Todo todos={todos}
    markComplete={() =>markComplete()}
    deleteTodo={() => deleteTodo()}
/>

** Todo组件:**

function Todo({ todos, markComplete, deleteTodo }) {
  return todos.map((todo) => (
    <TodoItem
      key={todo.id}
      markComplete={markComplete}
      deleteTodo={deleteTodo}
      todos={todos}
    />
  ))
}

TodoItem组件:

class TodoItem extends Component {
  render() {
    const { id, title } = this.props.todo // **Can you tell me this part? I did not understand and could not convert.**

    return (
      <div>
        <p>
          <input
            type="checkbox"
            onChange={this.props.markComplete.bind(this, id)}
          />
          {""} {title}{" "}
          <button onClick={this.props.deleteTodo.bind(this, id)}>X </button>{" "}
        </p>{" "}
      </div>
    )
  }
}

最后是Addtodo组件:(我不理解onSubmit函数中的“ Addtodo”。这是来自App.js还是类名的道具?

class Addtodo extends Component {
  state = {
    title: ""
  }

  onSubmit = (e) => {
    e.preventDefault()
    this.props.Addtodo(this.state.title) // // **Can you tell me this part? I did not understand and could not convert.**

    this.setState({
      title: ""
    })
  }

  onChange = (e) =>
    this.setState({
      [e.target.name]: e.target.value
    })

  render() {
    return (
      <form
        onSubmit={this.onSubmit}

      >
        <input
          type="text"
          name="title"
          onChange={this.onChange}
          value={this.state.title}
          placeholder="Add todo"
         
        />
        <input
          type="Submit"
          name="Submit"
          value="Submit"
          className="btn"
          
        />{" "}
      </form>
    )
  }
}

2 个答案:

答案 0 :(得分:0)

使用useStatestate的每个部分本身都具有一个var(除非您选择使其嵌套),而不是状态本身是对象的类组件。

>

因此,在setter函数中,您只需分配新值,而无需提及要更改的状态(todos)。

更改

setTodos({
    todos: res.data // i'm not sure about here.
})

收件人

setTodos(res.data)

setTodos({
  todos:[...todos.filter((todo) => todo.id !== id)] // not sure
})

收件人

setTodos([...todos.filter((todo) => todo.id !== id)])

此外,如果您要传递函数,则只需提及它而不调用它

<Todo todos={todos}
    markComplete={markComplete}
    deleteTodo={deleteTodo}
/>

TodoItem component

      // you extract "id" and "title" from "this.props.todo"
const { id, title } = this.props.todo

无需更改,因为您仍在使用类组件。

Addtodo component中,调用传递给它的函数,并将标题传递给该函数。

this.props.Addtodo(this.state.title)

由于您仍在使用类组件,因此不需要任何更改。

答案 1 :(得分:0)

让componentDidMount使用效果
您已将空数组[]添加为useEffect的第二个参数。

useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/todos?_limit=10")
      .then((res) =>
        setTodos({
          todos: res.data // i'm not sure about here.
        })
      )
  }, []);