reactjs - 状态更新错误
问题描述
我有一个错误试图更新 React 中的状态。这是我的setState
功能:
class App extends Component {
state = {
songs: [],
}
handleUpload = (songData) => {
var songs = [...this.state.songs, songData];
console.log(songs);
this.setState({songs});
}
render() {
return (
<div>
<div className="">
<SidebarTopOverlay
onUpload={this.handleUpload}
logo={logo}/>
这是console.log的结果:
(1) […]
0: Object { title: "asdf", description: "", songFile: [], … }
length: 1
__proto__: Array []
App.js:19
(2) […]
0: Object { title: "asdfasdf", description: "", songFile: [], … }
1: Object { title: "asdfasdf", description: "", songFile: [], … }
length: 2
__proto__: Array []
如您所见,某些内容直接覆盖了状态,因为(编辑)在第二个日志上它不应该打印songFields
要添加的重复项。
这是 UploadHandlers 类:
import React from 'react';
import UploadDropdown from '../../presentational-components/uploader/uploadDropdown.js';
const initialState = {
songUploadFields: {
title: '',
description: '',
songFile: [],
genres: [],
},
uploadButtonToggle: true,
}
class UploadHandlers extends React.Component{
state = initialState;
reset = () => {
this.setState(initialState);
}
handleInputChange = (e) => {
const name = e.target.name;
var value = e.target.value;
var songUploadFields = this.state.songUploadFields;
/*Title and SongFile are required to enable the upload button */
if(name === 'title' && value.length > 0){
this.setState({uploadButtonToggle: false});
}else if(name === 'title'){
this.setState({uploadButtonToggle: true});
}
/*don't allow two of the same genre,
and allow user to subtract genres*/
if(name === 'genres'){
var genres = this.state.songUploadFields.genres;;
if(!this.state.songUploadFields.genres.includes(value)){
genres.push(value);
value = genres;
}else{
var index = genres.indexOf(value)
genres.splice(index, 1);
value = genres;
}
//in case of songFile, change 'value' to handle file upload
}else if(name==='songFile'){
value = e.target.files[0];
}
//update the state
songUploadFields[name] = value;
this.setState({songUploadFields});
}
handleUpload = () => {
this.props.onUpload(this.state.songUploadFields);
this.reset();
}
render(){
return(
<UploadDropdown
onUpload={this.handleUpload}
onInputChange={this.handleInputChange}
data={this.state}
/>
)
}
}
export default UploadHandlers
和 UploadDropdown (仅在模式中呈现它):
<Uploader
onUpload={this.props.onUpload}
onInputChange={this.props.onInputChange}
data={this.props.data}
/>
和上传者:
import React from 'react';
import {Form, Button, Input, Dropdown} from 'semantic-ui-react';
/*Uploader is the form for uploading songs */
class Uploader extends React.Component{
render(){
const genres = [
{
key: 0,
text: 'world',
value: 'world',
},
{
key: 1,
text: 'folk',
value: 'folk',
},
{
key: 2,
text: 'psychedelic',
value: 'psychedelic',
},
{
key: 3,
text: 'funk',
value: 'funk',
},
];
return(
<div>
<Form onSubmit={this.props.onUpload}>
<Form.Field>
<Input
name='songFile'
type="file"
multiple
onChange={this.props.onInputChange} />
</Form.Field>
<Form.Field>
<label>Title</label>
<Input
type='text'
name='title'
placeholder='Title'
value={this.props.data.songUploadFields.title}
onChange={this.props.onInputChange}/>
</Form.Field>
<Form.Field>
<label>Description</label>
<Input
type='text'
name='description'
placeholder='Description'
value={this.props.data.songUploadFields.description}
onChange={this.props.onInputChange}/>
</Form.Field>
<Form.Field>
<label>Genres</label>
<select
name='genres'
multiple
value={this.props.data.songUploadFields.genres}
onChange={this.props.onInputChange}>
{genres.map((g, i) => <option key={i} value={g.value}>{g.text}</option>)}
</select>
</Form.Field>
<Button type='submit' disabled={this.props.data.uploadButtonToggle}>Upload</Button>
</Form>
</div>
)
}
}
export default Uploader;
任何帮助,将不胜感激。
解决方案
问题是您的state
操作不断修改与 共享的一组对象initialState
,而不是创建新值,例如:
var genres = this.state.songUploadFields.genres;
if (!this.state.songUploadFields.genres.includes(value)) {
genres.push(value);
value = genres;
}
genres
是与 相同的对象引用initialState.songUploadFields.genres
。当你推动它时,你也在改变initialState
,破坏你的reset
功能。
您总是需要创建一个副本,例如:
var genres = this.state.songUploadFields.genres.slice();
同样的问题也发生在songUploadFields
对象上。它也与 中的对象完全相同initialState.songUploadFields
。您需要在开始修改之前创建一个副本,例如:
var songUploadFields = Object.assign({}, this.state.songUploadFields);
推荐阅读
- spring-boot - 如何在 springboot graphql 应用程序中设置基本 url
- moqui - Moqui - 将多个资产关联到一个资产
- javascript - 为什么只有我的第一个模态按预期加载?
- math - 当事件比测量时间慢时平均
- tabulator - 使用 Tabulator 表在打印模式下重复列标题
- vim - 是否可以映射以执行正常命令?
- matlab - Matlab - 调用函数文件的函数文件的路径
- c# - UDP over NAT(通过互联网)
- javascript - SailsJS V1 - 蓝图查询无法正常工作
- c# - 如何将 SDK jar 文件转换为 .Net dll 文件