将此 react class 组件更改为 react hooks

Change this react class component into react hooks

我正在观看此视频中的 MERN Stack 教程 MERN。 在 1:41:16 - 1:47:01 部分 我正在尝试将所有内容转换为反应挂钩,并且一切顺利,直到 exercise-list component

这是我将其转换为 react-hook 组件时的代码。

import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios'

const Exercise = item => {
    <tr>
        <td>{item.exercise.username} </td>
        <td>{item.exercise.description} </td>
        <td>{item.exercise.duration} </td>
        <td>{item.exercise.date.substring(0,10)} </td>
        <td><Link to={"/edit/" + item.exercise._id}> Edit</Link> | 
        <a href="#" onClick={e => {item.handledeleteExercise(item.exercise._id)}}> delete </a>
        
        </td>

    </tr>
}

function Exercises_List(props) {

    const [deleteExercise,setdeleteExercise] = useState()

    const [exercises,setexercises] = useState([])

    useEffect(() => {
        axios.get('http://localhost:4500/exercises/')
            .then(res => {
                setexercises([...exercises,res.data])
            })
            .catch(err => console.log(err))
    },[])

    const handledeleteExercise = (id) => {
        axios.delete('http://localhost:4500/exercises'+id)
            .then(res => console.log(res.data));
        const filtered = exercises.filter((el) => el._id !== id)
        setexercises(filtered)
    }

    const exerciseList = () => {
        return exercises.map(currentexercise => {
            return <Exercise 
                exercise={currentexercise} 
                handledeleteExercise={e => handledeleteExercise(e)}
                key={currentexercise._id}></Exercise>
        })
    }

  
    return (
  
        <div>
            <h3> Logged Exercises</h3>
            <table className="table">
                <thead className="thead-light">
                    <tr>
                        <th>Username </th>
                        <th>Description </th>
                        <th>Duration </th>
                        <th>Date </th>
                        <th>Actions </th>
                    </tr>
                </thead>
                <tbody>
                    {exerciseList()}
                </tbody>
            </table>


        </div>
  
        )
}

export default Exercises_List

唯一让我困惑的是const [deleteExercise,setdeleteExercise] = useState() 正如你在 1:41:22 的视频中看到的那样..我很困惑我应该如何使用 deleteExercise 将它转换为 react-hooks.. 我试过这样的东西

deleteExercise = e => {
 ....
}
``` But I know that is out of the rules in react hooks...Another thing I look at here is this part of 
useEffect(() => {
    axios.get('http://localhost:4500/exercises/')
        .then(res => {
            setexercises({...exercises:res.data})
        })
        .catch(err => console.log(err))
},[])

once I show this in my output 



   {exerciseList()}

它给我这样的错误TypeError: exercises.map is not a function

我想我在这里错过了一个想法......我也对 edit-exercises.component 的部分感到困惑,其中它在 1:43:32 的部分传递了 props.match.params.id..

伙计们,我快死了..我非常想制作简单的全栈网站,但我就是做不到哈哈...教程和我的文档学习特别是更新和文档令人困惑。

我无法解释这一切,对此我深表歉意...我想在这里解决的是将其转换为 react-hooks,因为 react class 组件在我的本性中并不是很有用。

我认为你的代码失败是因为:

setexercises({...exercises:res.data})

该语句在 exercises 变量中存储 一个对象 ,并且对象没有 map 方法。

(实际上,我认为该语句不是有效语法:您不能在也有值的 属性 名称前放置三个点。您可以这样做:({ ...res.data }) 或这个({ exercises: res.data })——尽管两者仍然会以相同的方式中断,因为它们都存储一个对象而不是一个数组。但这些至少是有效的ES6语法。)

我怀疑更大的问题是你没有正确考虑你的数据。

  • 你有一个练习列表
  • 您希望能够在该列表中添加和删除项目

很明显你只需要一个数组。那个数组是你应该使用 React 的 useState 钩子存储的:

let [ exercises, setExercises ] = React.useState([])

因此:exercises 是列表(具有 map 方法的数组),而 setExercises 让您可以完全覆盖该数组。请注意最后一块:useState 挂钩提供的唯一工具 是一个破坏整个列表 的工具。这意味着您的“添加”和“删除”操作必须仅使用该工具来完成它们的任务。

所以,你必须完成这个函数的实现:

function addExercise( newExercise ) {
  /*
    STEP 1: calculate fresh array that contains
    all the current exercises plus newExercise.
  */
  let newList = [/* TODO */]

  /*
    STEP 2: overwrite current list using the
    only tool provided by useState. This updates
    the data *and* immediately re-renders the
    component with the new data.
  */
  setExercises(newList)
}

同样的想法适用于从列表中删除练习:

function removeExercise( exerciseToRemove ) {
  /*
    STEP 1: calculate fresh array that contains
    all the current exercises minus exerciseToRemove.
  */
  let newList = [/* TODO */]

  /*
    STEP 2: overwrite current list using the
    only tool provided by useState.
  */
  setExercises(newList)
}

当您 API 调用 returns:

时,同样的工具也是您更新列表的方式
useEffect(() => {
  axios.get('http://localhost:4500/exercises/')
  // this assumes that res.data is an array
  .then(res => setExercises(res.data))
  .catch(err => console.log(err))
}, [])

此外:您的练习组件可能无法解析。包裹body的花括号需要是圆括号,或者body里面需要一个return语句:

// bad!
const MyComp = props => { <div> thing </div> }

// good
const MyComp = props => ( <div> thing </div> )

// also good
const MyComp = props => { return (<div> thing </div>) }