最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React <Switch> is not getting updated or changing its state - Stack Overflow

programmeradmin2浏览0评论

Hey guys I am learning react and have a form to edit book details. I am using django in the backend. I am not able to update the e-book which is a switch to turn on and off according to whether e-book is available or not. The switch works fine, but no data is being changed in the database. I am confused on how to work with the switch and saw lots of resources saying different things which is quite difficult to understand. Rest of the fields are getting updated correctly. Can someone tell me what changes I have to make in this switch to make it work??

code

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 ponent="main" maxWidth="sm">
                    <CssBaseline />
                    <div className={classes.paper}>
                        <Typography ponent="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;

Hey guys I am learning react and have a form to edit book details. I am using django in the backend. I am not able to update the e-book which is a switch to turn on and off according to whether e-book is available or not. The switch works fine, but no data is being changed in the database. I am confused on how to work with the switch and saw lots of resources saying different things which is quite difficult to understand. Rest of the fields are getting updated correctly. Can someone tell me what changes I have to make in this switch to make it work??

code

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 ponent="main" maxWidth="sm">
                    <CssBaseline />
                    <div className={classes.paper}>
                        <Typography ponent="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;
Share Improve this question edited Apr 18, 2021 at 6:35 Linda Paiste 42.4k8 gold badges80 silver badges116 bronze badges asked Oct 31, 2020 at 16:05 prehistoricbeastprehistoricbeast 4351 gold badge7 silver badges18 bronze badges 1
  • Shouldn't you actually pass props to switch by props of Controller? Meaning <Controller value = {formData.e_book}..., instead of directly on switch like you do. And if you do want to pass it directly to ponent you would need to use "render" instead of "as" if i am not mistaken – Nikita Chayka Commented Nov 1, 2020 at 12:12
Add a ment  | 

3 Answers 3

Reset to default 4

You are passing props to Switch directly, but what you should do is to use Controller props, and Controller will then pass it down to Switch:

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

Otherwise you need to use render, not as This is actually described pretty good here: https://react-hook-form./api/#Controller


UPDATE

Here is the sandbox where it is working fine with above changes - https://codesandbox.io/s/kind-nash-s94v0

What i did there is simply this:

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

/>

You are initializing the value as a string at the beginning of BookEdit(). Try to set initialFormData like this:

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

My solution:

<FormControlLabel
  control={
    <Controller
      name='customerio.status'
      control={control}
      defaultValue={initialValues?.customerio?.status || false}
      render={({ field }) => (
        <Switch
          checked={field.value}
          onChange={event => {
            field.onChange(event.target.checked);
          }}
          color='success'
          inputProps={{ 'aria-label': 'controlled' }}
        />
      )}
    />
  }
  label={t('active')}
/>
发布评论

评论列表(0)

  1. 暂无评论