我有一个试图在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;
任何帮助都将不胜感激。
答案 0 :(得分:1)
问题是,您的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);