编辑功能不适用于我的 CRUD 应用程序

Edit function not working for my CRUD App

我正在构建一个简单的 CRUD 应用程序,我有 90% 的工作正常,但由于某种原因我无法使用“编辑”功能。当我去编辑我的团队成员姓名时,单击“编辑姓名”时没有任何反应。值得注意的是,我从我的“添加用户”组件中复制了代码并进行了修改。这是我的代码:

// 编辑用户

import React, { useState, useContext, useEffect } from 'react'
import { GlobalContext } from '../context/GlobalState'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { Form, FormGroup, Label, Input, Button } from 'reactstrap'

const EditUser = (props) => {
const [selectedUser, setSelectedUser] = useState({
  id: '',
  name: ''
});
const { users, editUser } = useContext(GlobalContext);
const navigate = useNavigate();
const currentUserId = useParams(props);

useEffect(() => {
  const userId = currentUserId;
  const selectedUser = users.find((user) => user.id === userId);
  if (selectedUser) {
    setSelectedUser(selectedUser);
  } 
}, [currentUserId, users]);

const onSubmit = (e) => {
  e.preventDefault()
  editUser(selectedUser)
  navigate('/');
}

const onChange = (e) => {
  setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
}

  return (
    <div className='container w-25'>
        <Form className='form-control' onSubmit={onSubmit}>
            <FormGroup>
                <Label>Edit Name</Label>
                <Input type='text' name='name' value={selectedUser.name} onChange={onChange} placeholder='Enter Name'></Input>
            </FormGroup>
        <Button type='submit'>Edit Name</Button>
        <Link to='/' className='btn btn-danger m-2'>Back</Link>
        </Form>
    </div>
  )
}

export default EditUser

// 添加用户

import React, { useState, useContext } from 'react'
import { GlobalContext } from '../context/GlobalState'
import { Link, useNavigate } from 'react-router-dom'
import { v4 as uuid } from 'uuid';
import { Form, FormGroup, Label, Input, Button } from 'reactstrap'

const AddUser = () => {
  const [name, setName] = useState('');
  const { addUser } = useContext(GlobalContext);
  const navigate = useNavigate();

  const onSubmit = (e) => {
    e.preventDefault()
    const newUser = {
      id: uuid(),
      name: name
    }
    addUser(newUser);
    navigate('/');
  }

  const onChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div className='container w-25'>
        <Form className='form-control' onSubmit={onSubmit}>
            <FormGroup>
                <Label>Name</Label>
                <Input 
                type='text' 
                name={name} 
                value={name} 
                onChange={onChange} 
                placeholder='Enter Name'></Input>
            </FormGroup>
        <Button type='submit'>Submit</Button>
        <Link to='/' className='btn btn-danger m-2'>Back</Link>
        </Form>
    </div>
  )
}

export default AddUser

// 全局上下文

import React, { createContext, useReducer } from 'react';
import AppReducer from './AppReducer';

const initialState = {
        users: []
    };

// Create Context \

export const GlobalContext = createContext(initialState);

// Provider Component \

export const GlobalProvider = ({children}) => {
    const [state, dispatch] = useReducer(AppReducer, initialState);

    // Actions

    const removeUser = (id) => {
        dispatch({
            type: 'REMOVE_USER',
            payload: id
        });
    }

    const addUser = (user) => {
        dispatch({
            type: 'ADD_USER',
            payload: user
        });
    }

    const editUser = (user) => {
        dispatch({
            type: "EDIT_USER",
            payload: user
        });
    }

    return(
        <GlobalContext.Provider value={{
            users: state.users,
            removeUser,
            addUser,
            editUser
        }}>
            {children}
        </GlobalContext.Provider>
    )
}

// 应用减速器

export default (state, action) => {
    switch(action.type) {
        case 'REMOVE_USER':
            return {
                users: state.users.filter(user => {
                    return user.id !== action.payload
                })
            }

            case 'ADD_USER':
                return {
                    users: [action.payload, ...state.users]
                }
            case 'EDIT_USER':
                const updateUser = action.payload
                const updateUsers = state.users.map(user => {
                    if(user.id === updateUser.id) {
                        return updateUser;
                    }
                    return user;
                })

                return {
                    users: updateUsers
                }
        
        default:
            return state
    }
}

问题

问题似乎是 Edit 组件没有正确访问路由路径参数对象,以引用路由路径的 userId 参数。

const currentUserId = useParams();

useEffect(() => {
  const userId = currentUserId;
  const selectedUser = users.find((user) => user.id === userId);
  if (selectedUser) {
    setSelectedUser(selectedUser);
  } 
}, [currentUserId, users]);

这里整个params对象被命名为currentUserId。在 useEffect 挂钩回调中,此参数对象被分配给局部变量 userId,然后用于在 users 数组中查找匹配的用户对象。它将特定用户的 id 属性(字符串类型)与整个参数对象(对象类型)进行比较.此 OFC 永远不会相等并且 selectedUser 未定义并且本地 selectedUser 状态永远不会初始化为您尝试编辑的用户。

解决方案

访问params对象以正确访问特定参数:

const currentUserId = useParams();

useEffect(() => {
  const userId = currentUserId;
  const selectedUser = users.find((user) => user.id === userId.userId);
  if (selectedUser) {
    setSelectedUser(selectedUser);
  } 
}, [currentUserId, users]);

或者直接解构userId路径参数:

const { userId } = useParams();

useEffect(() => {
  const selectedUser = users.find((user) => user.id === userId);
  if (selectedUser) {
    setSelectedUser(selectedUser);
  } 
}, [userId, users]);

建议

直接初始化selectedUser状态。使用 useEffect 挂钩检查是否有用户要编辑,如果没有用户要编辑则返回导航。

const EditUser = () => {
  const navigate = useNavigate();
  const { userId } = useParams();
  const { users, editUser } = useGlobalContext(); // *

  const [selectedUser, setSelectedUser] = useState(
    users.find((user) => user.id === userId)
  );

  useEffect(() => {
    if (!selectedUser) navigate(-1);
  }, [navigate, selectedUser]);

  const onSubmit = (e) => {
    e.preventDefault();
    editUser(selectedUser);
    navigate("/");
  };

  const onChange = (e) => {
    setSelectedUser({ ...selectedUser, [e.target.name]: e.target.value });
  };

  return (
    <div className="container w-25">
      {selectedUser && (
        <Form className="form-control" onSubmit={onSubmit}>
          <FormGroup>
            <Label>Edit Name</Label>
            <Input
              type="text"
              name="name"
              value={selectedUser.name}
              onChange={onChange}
              placeholder="Enter Name"
            />
          </FormGroup>
          <Button type="submit">Edit Name</Button>
          <Link to="/" className="btn btn-danger m-2">
            Back
          </Link>
        </Form>
      )}
    </div>
  );
};

* 注意:这只是为了方便在上下文代码中创建的自定义挂钩:

const useGlobalContext = () => useContext(GlobalContext);