不受控制的输入反应
Posted
技术标签:
【中文标题】不受控制的输入反应【英文标题】:Uncontrolled input React 【发布时间】:2020-10-09 21:40:20 【问题描述】:我有以下代码:
import React, Component from 'react'
import axios from 'axios'
import Navbar from '../Navbar'
import Avatar, TextField, Button, Container, CircularProgress from '@material-ui/core'
import Alert from '@material-ui/lab/Alert'
class PrivateProfile extends Component
constructor(props)
super(props);
this.state =
user: null,
id: null,
image: null,
pp: null,
username: 'AnonymousUser',
showSuccess: false
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.handleFileChange = this.handleFileChange.bind(this)
componentDidMount()
axios.get('http://127.0.0.1:8000/users/profile')
.then(res =>
this.setState(
user: res.data,
id: res.data.id,
username: res.data.username,
pp: res.data.pp
)
)
.catch(err => console.log(err))
handleSubmit(e)
e.preventDefault()
const fd = new FormData()
fd.append('pp', this.state.image)
fd.append('username', this.state.user.username)
fd.append('email', this.state.user.email)
fd.append('bio', this.state.user.bio)
const d =
pp : this.state.image,
username : this.state.user.username,
email : this.state.user.email,
bio : this.state.user.bio
console.log('d', d)
console.log('fd', fd)
axios.put(`http://127.0.0.1:8000/users/profile/update/$this.state.id/`, fd,
headers:
'Content-Type': 'multipart/form-data'
)
.then(res =>
this.setState(
user: res.data,
id: res.data.id,
pp: res.data.pp,
image: null,
username: res.data.username,
showSuccess: true
)
)
.catch(err => console.log(err))
handleChange(e)
this.setState(
user:
[e.target.name]: e.target.value
)
handleFileChange(e)
this.setState(image: e.target.files[0])
render()
let message
let alert
if (this.state.user !== null)
if (!this.state.user.bio)
message = <h4>Please update your profile below.</h4>
if (this.state.showSuccess)
alert = <Alert action=<Button onClick=() => this.setState(showSuccess: false)>Close</Button> severity='success'>Profile Successfully Updated</Alert>
return (
<div>
<Navbar />
<Container style=background: '#f7f4e9'>
<div style=height: '60px'></div>
<h2>Your Profile</h2>
<Avatar src=this.state.user.pp alt=this.state.user.username />
message
alert
<h4>Your data:</h4>
<form onSubmit=this.handleSubmit>
<p>Profile Pic</p>
<input type="file" onChange=this.handleFileChange/>
<br></br>
<br></br>
<TextField label='Username' name="username" onChange=this.handleChange type="text" value=this.state.user.username />
<br></br>
<br></br>
<TextField label='Email' name="email" onChange=this.handleChange type="email" value=this.state.user.email />
<br></br>
<br></br>
<TextField label='Bio' name="bio" onChange=this.handleChange type="text" value=this.state.user.bio />
<br></br>
<br></br>
<br></br>
<Button type="submit" value="submit">Update</Button>
</form>
</Container>
</div>
)
else
return <CircularProgress />
export default PrivateProfile
我收到错误消息:警告:组件正在将文本类型的受控输入更改为不受控制。输入元素不应从受控切换到不受控(反之亦然)。决定在组件的生命周期内使用受控输入元素还是不受控输入元素。
谁能帮我修一下。
【问题讨论】:
您能否确保用户名、电子邮件和个人简历不为空值。例如 value=this.state.user.username || '' 这能回答你的问题吗? React - changing an uncontrolled input 当我做 value=this.state.whatever || '',每当其中一个字段发生变化时,其他字段也会变成空字符串 如我所见,您必须在 handleChange 中合并旧状态。 this.setState( user: ...this.state.user, [e.target.name]: e.target.value ) 乍一看这似乎是正确的。您是否尝试过调试您的 handleChange 方法?它是否根据输入的名称访问正确的键? 【参考方案1】:由于您使用 null 初始化状态值并像 value=this.state.user.username
一样使用它,并更新状态,您会收到这样的错误:
警告:组件正在将文本类型的受控输入更改为不受控制。
要控制它的状态,像这样使用它:
value=this.state.user.username || ''
根据我的评论,您在这里有问题:
handleChange(e)
this.setState(
user:
[e.target.name]: e.target.value
)
用户状态总是会随着你的任何输入变化而改变,你需要像这样:
handleChange(e)
this.setState(
user:
...this.state.user,
[e.target.name]: e.target.value
)
【讨论】:
当我做 value=this.state.whatever || '',每当其中一个字段发生变化时,其他字段也会变成空字符串 那么,这不是那个问题。您可以查看 onChange 处理程序。 这个答案应该是正确的。我喜欢切换到useState
钩子的众多原因之一 - 更新嵌套状态时不再需要以旧状态传播。假设您正在构建一个平面数据结构。
最好用''
而不是null
来初始化表单值。然后你不需要在任何地方都做value || ''
,并且可以相信它们在代码的其他部分也是不可为空的。
@ATOMP 是的。但在某些情况下,我们可能需要有 null
值,例如。初始状态用于获取某些结果?以上是关于不受控制的输入反应的主要内容,如果未能解决你的问题,请参考以下文章