【问题标题】:Problem converting class component to functional component将类组件转换为功能组件时出现问题
【发布时间】:2020-11-11 14:53:32
【问题描述】:

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

类到函数

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

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


ComponentDidMount to useEffect

  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 的 Props 还是类名?

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>
    )
  }
}

【问题讨论】:

    标签: javascript reactjs functional-programming react-hooks


    【解决方案1】:

    使用useState,您可以将state 的每一部分都放在一个变量中(除非您选择使其嵌套),而不是在状态本身是一个对象的类组件中。

    因此,在 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)
    

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

    【讨论】:

    • 非常感谢您的回答。你的解释对我帮助很大。我做了你在 AddTodo 部分所做的更正。你能检查最后一节。我做对了吗?
    • @navarrro ninca 所有部分都在一个组件中吗?
    • @navarrro ninca 查看我对答案的更新,(我很难看到你的结构,但这就是我的样子)
    • 我关注你的更新。我在问题的底部添加了其他组件。
    • @navarrro ninca 我添加了一些更新,如果您还有任何问题,请告诉我。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2020-10-17
      • 2020-06-28
      • 1970-01-01
      • 2021-04-01
      • 2020-02-08
      • 2020-08-26
      • 1970-01-01
      • 2022-01-08
      相关资源
      最近更新 更多