Javascript Can';t使用setState更新对象属性
我正在创建一个简单的应用程序。我将我的卡片/公告存储在BulletinsList.js中,将单个公告/卡片存储在bulletins.js中 我试图更改第一个公告中的“Hello World”(使用Bulletin.js中的输入,通过单击标题并将其切换为输入)标题,但没有任何效果,所以基本上我无法更新存储在数组中的对象的属性。我正在传递一个object的id,但它不能正常工作。谁能给我一个答案我怎么能做到 BulletinList.jsJavascript Can';t使用setState更新对象属性,javascript,reactjs,Javascript,Reactjs,我正在创建一个简单的应用程序。我将我的卡片/公告存储在BulletinsList.js中,将单个公告/卡片存储在bulletins.js中 我试图更改第一个公告中的“Hello World”(使用Bulletin.js中的输入,通过单击标题并将其切换为输入)标题,但没有任何效果,所以基本上我无法更新存储在数组中的对象的属性。我正在传递一个object的id,但它不能正常工作。谁能给我一个答案我怎么能做到 BulletinList.js import React, { Component } fr
import React, { Component } from 'react';
import Bulletin from '../Bulletin/Bulletin';
class BulletinList extends Component {
state = {
bulletin: [
{
id: 1,
title: 'Hello World',
listOfTasks: ['eat sandwich', 'clean house']
},
{
id: 2,
title: 'Hello Mars',
listOfTasks: ['eat spaghetti', 'go to sleep']
},
],
titleField: '',
descriptionField: ''
}
addEmptyCard = () => {
this.setState({
bulletin: [...this.state.bulletin, {id: this.state.bulletin.length + 1, title: '...', listOfTasks: []}]
})
}
captureInput = (event, id) => {
const specificCard = this.state.bulletin[id - 1];
this.setState(prevState => ({
[specificCard]: {
...prevState.specificCard,
title: event.target.value
}
}))
}
render() {
return(
<div>
<button onClick={this.addEmptyCard}>+</button>
{this.state.bulletin.map((element => {
return <Bulletin
id={element.id}
title={element.title}
list={element.listOfTasks}
captureInput={this.captureInput}/>
}))}
</div>
)
}
}
export default BulletinList;
import React,{Component}来自'React';
从“../Bulletin/Bulletin”导入公告;
类BulletinList扩展组件{
状态={
公告:[
{
id:1,
标题:“你好,世界”,
任务清单:[“吃三明治”、“打扫房间”]
},
{
id:2,
标题:“你好,火星”,
任务列表:[“吃意大利面”,“睡觉”]
},
],
titleField:“,
descriptionField:“”
}
addEmptyCard=()=>{
这是我的国家({
公告:[…this.state.bulletin,{id:this.state.bulletin.length+1,标题:'…',任务列表:[]]
})
}
captureInput=(事件,id)=>{
const specificCard=此.state.bulletin[id-1];
this.setState(prevState=>({
[特定卡片]:{
…prevState.specificCard,
标题:event.target.value
}
}))
}
render(){
返回(
+
{this.state.bulletin.map((元素=>{
返回
}))}
)
}
}
导出默认公告列表;
Bulletin.js
import React, { useState } from 'react';
const Bulletin = ({ id, title, list, captureInput }) => {
const [inputOn, setInputOn] = useState(false);
return(
<div>
{!inputOn ? <h1 onClick={() => setInputOn(!inputOn)}>{title}</h1>
:
<div>
<input type="text" onChange={(event) => captureInput(event, id)}/>
<button onClick={() => setInputOn(!inputOn)}>Change title</button>
</div>}
{list.map(element => {
return <p>{element}</p>
})}
<input type="text" />
</div>
)
}
export default Bulletin;
import React,{useState}来自“React”;
常量公告=({id、标题、列表、captureInput})=>{
const[inputOn,setInputOn]=useState(false);
返回(
{!inputOn?setInputOn(!inputOn)}>{title}
:
captureInput(事件,id)}/>
setInputOn(!inputOn)}>更改标题
}
{list.map(元素=>{
返回{element}
})}
)
}
导出默认公告;
在captureInput
中,您不会覆盖公告
属性,而是使用对象作为索引创建一个新属性。解决此问题的正确方法之一是:
captureInput = (event, id) => {
const newBulletin = [...this.state.bulletin];
newBulletin[id - 1].title = event.target.value;
this.setState({
bulletin: newBulletin
});
}
我在这里使用扩展语法创建一个新数组,然后在给定位置覆盖元素的title
属性
另外,您将元素的id
传递给公告组件,然后将其用作索引。它现在可以工作,因为标识符是有序的,但最好通过迭代数组来找到真正的索引:
captureInput = (event, id) => {
const elemIndex = this.state.bulletin.findIndex(elem => elem.id === id);
const newBulletin = [...this.state.bulletin];
newBulletin[elemIndex].title = event.target.value;
this.setState({
bulletin: newBulletin
});
}
这样,您就可以在不破坏应用程序的情况下删除项目。谢谢!我还有一个问题,你知道为什么这个函数不能正常工作吗?它涉及到删除特定任务,如“吃意大利面”
deleteTask=(id)=>{const specificblutin=this.state.bulletin[id-1].listOfTasks;this.setState({specificblutin:specificblutin.splice(id-1,1),})
同样的原因-您正在状态中创建“specificBulletin”属性。复制我上面发布的代码,但不要覆盖标题
筛选出要删除的任务:newBulletin[elemIndex].listoftask=newBulletin[elemIndex].listoftask.filter(element=>element.id!==id)
。它将创建一个新数组,而不包含具有给定id
的元素。黄金法则是在更新状态时始终提供新引用(不变性)。