React <Switch> 未更新或更改其状态

React <Switch> is not getting updated or changing its state

大家好,我正在学习 React,并且有一个表格可以编辑书籍的详细信息。我在后端使用 django。我无法根据电子书是否可用来更新 switch 打开和关闭的电子书。开关工作正常,但数据库中没有数据被更改。我对如何使用 switch 感到困惑,看到很多资源都在说不同的东西,这很难理解。其余字段正在正确更新。谁能告诉我我必须对此 switch 进行哪些更改才能使其正常工作?

代码

import React, {useEffect, useState} from 'react'
import axiosInstance from '../../axios';
import { useForm, Controller } from 'react-hook-form';

//MaterialUI
import Button from '@material-ui/core/Button';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import Select from '@material-ui/core/Select';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';


const useStyles = makeStyles((theme) => ({
    paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
    },
    bookformbody: {
        display: "flex",
        backgroundColor: "#ffff",
        height: "100vh",
    },
    form: {
        width: '100%', // Fix IE 11 issue.
        marginTop: theme.spacing(3),
    },
    submit: {
        margin: theme.spacing(3, 0, 2),
    },
}));


function BookEdit() {    
    const initialFormData = Object.freeze({
        id: '',
        summary: '',
        published_date: '',
        e_book: false,
    });

    const [formData, updateFormData] = useState(initialFormData);

    useEffect(() => {
        axiosInstance.get('api/books/details/view/').then((res) => {
            updateFormData({
                ...formData,
                ['summary']: res.data.summary,
                ['published_date']: res.data.published_date,
                                ['e_book']: res.data.e_book,

            });
            console.log(res.data);
        });
    }, [updateFormData]);

    const handleChange = (e) => {
        if(e.target.name === "e_book"){
             return(
                 updateFormData({
                     ...formData,
                     [e.target.name]: e.target.checked
                 })
                
             )
        }   
        updateFormData({
            ...formData,         
            // Trimming any whitespace
            [e.target.name]: e.target.value
        });
    };


    const onSubmit = (data) =>{
        let formData = new FormData();

        formData.append('summary', data.summary);
        formData.append('published_date', data.published_date);
        formData.append('e_book', data.e_book);

        axiosInstance.put('api/books/details/edit/', formData);

    } ;
    
    const classes = useStyles();
    const { register, handleSubmit, control, errors } = useForm();

    return (
        <>
            <Header />
            <div className={classes.bookformbody}>
                <SideBar />
                <Container component="main" maxWidth="sm">
                    <CssBaseline />
                    <div className={classes.paper}>
                        <Typography component="h1" variant="h5">
                            Edit Book Details
                        </Typography>
                        <form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
                            <Grid container spacing={2}>
                                <Grid item xs={12}>
                                    <TextField
                                        variant="outlined"
                                        required
                                        fullWidth
                                        id="summary"
                                        label="Book Summary"
                                        name="summary"
                                        autoComplete="summary"
                                        value={formData.summary}
                                        onChange={handleChange}
                                        inputRef={register({maxLength: 1000})}
                                        multiline
                                        rows={4}
                                    />
                                </Grid>

                                <Grid item xs={12}>
                                    <TextField
                                        variant="outlined"
                                        required
                                        fullWidth
                                        type="date"
                                        label="Published Date"
                                        name="published_date"
                                        autoComplete="published_date"
                                        value={formData.published_date}
                                        onChange={handleChange}
                                        inputRef={register({required: true})}
                                        InputLabelProps={{
                                            shrink: true,
                                          }}
                                    />
                                </Grid>

                                <Grid item xs={12}>
                                    <InputLabel id="e-book-switch">E-Book</InputLabel>
                                        <Controller
                                            name="e_book"
                                            control={control}
                                            as={
                                                <Switch size="small"
                                                    id="e-book-switch" 
                                                    type="checkbox"
                                                    name="e_book"
                                                    onChange={handleChange} 
                                                    // inputRef={register}
                                                    value={formData.e_book}
                                                    checked={formData.e_book}
                                                />
                                            }
                                        />
                                </Grid>
                            </Grid>
                            <Button
                                type="submit"
                                fullWidth
                                variant="contained"
                                color="primary"
                                className={classes.submit}
                            >
                                Update
                            </Button>
                        </form>
                    </div>
                </Container>
            </div>
        </>
    )
}

export default BookEdit;

您正在 BookEdit() 的开头将值初始化为字符串。尝试这样设置 initialFormData

const initialFormData = Object.freeze({
        id: '',
        summary: '',
        published_date: '',
        e_book: false,
    });

你是直接传递 props 给 Switch,但你应该做的是使用 Controller props,然后 Controller 会把它传递给 Switch:

<Controller as={Switch} value={formData.e_book} ... />

否则你需要使用render,而不是as 这实际上在这里描述得很好: https://react-hook-form.com/api/#Controller


更新

这是沙箱,它在进行上述更改后可以正常工作 - https://codesandbox.io/s/kind-nash-s94v0

我在那里所做的就是这样:

  <Controller
  name="e_book"
  control={control}
  render={(props) => {
   return (
     <Switch
      size="small"
      id="e-book-switch"
      type="checkbox"
      name="e_book"
      onChange={handleChange}
      // inputRef={register}
      value={formData.e_book}
      checked={formData.e_book}
    />
   );
}}

/>