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}
/>
);
}}
/>
大家好,我正在学习 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}
/>
);
}}
/>