Javascript 如何将json数据添加到数组onClick?

Javascript 如何将json数据添加到数组onClick?,javascript,arrays,json,reactjs,fetch,Javascript,Arrays,Json,Reactjs,Fetch,我是在项目中反应/使用API json数据的新手,所以有点麻烦。我创建了一个函数,用户可以在其中键入搜索查询,并显示与查询关联的设备列表。这些设备名称是从API获取的。我试图使它成为这样,当点击设备旁边的加号时,它会将该设备添加到一个新数组中,然后显示在屏幕上 我不是100%熟悉React中的状态概念,我认为这就是我的问题所在(在addDevice函数中)。它部分工作,我单击设备,它显示在底部,但当我单击另一个设备时,它不是添加到列表中,而是替换第一个设备 class App extends R

我是在项目中反应/使用API json数据的新手,所以有点麻烦。我创建了一个函数,用户可以在其中键入搜索查询,并显示与查询关联的设备列表。这些设备名称是从API获取的。我试图使它成为这样,当点击设备旁边的加号时,它会将该设备添加到一个新数组中,然后显示在屏幕上

我不是100%熟悉React中的状态概念,我认为这就是我的问题所在(在addDevice函数中)。它部分工作,我单击设备,它显示在底部,但当我单击另一个设备时,它不是添加到列表中,而是替换第一个设备

class App extends React.Component {
  state = {
    search: "",
    devices: [],
    bag: []
  };

  addDevice = (e, data) => {
    console.log(data);
    const newData = [this.state.devices.title];
    this.setState({
      bag: newData.concat(data)
    });
  };

  onChange = e => {
    const { value } = e.target;
    this.setState({
      search: value
    });

    this.search(value);
  };

  search = search => {
    const url = `https://www.ifixit.com/api/2.0/suggest/${search}?doctypes=device`;

    fetch(url)
      .then(results => results.json())
      .then(data => {
        this.setState({ devices: data.results });
      });
  };

  componentDidMount() {
    this.search("");
  }

  render() {
    return (
      <div>
        <form>
          <input
            type="text"
            placeholder="Search for devices..."
            onChange={this.onChange}
          />
          {this.state.devices.map(device => (
            <ul key={device.title}>
              <p>
                {device.title}{" "}
                <i
                  className="fas fa-plus"
                  style={{ cursor: "pointer", color: "green" }}
                  onClick={e => this.addDevice(e, device.title)}
                />
              </p>
            </ul>
          ))}
        </form>
        <p>{this.state.bag}</p>
      </div>
    );
  }
}
类应用程序扩展了React.Component{
状态={
搜索:“,
设备:[],
袋子:[]
};
添加设备=(e,数据)=>{
控制台日志(数据);
const newData=[this.state.devices.title];
这是我的国家({
包:newData.concat(数据)
});
};
onChange=e=>{
const{value}=e.target;
这是我的国家({
搜索:值
});
这个。搜索(值);
};
搜索=搜索=>{
常量url=`https://www.ifixit.com/api/2.0/suggest/${search}?doctypes=device`;
获取(url)
.then(results=>results.json())
。然后(数据=>{
this.setState({devices:data.results});
});
};
componentDidMount(){
此项。搜索(“”);
}
render(){
返回(
{this.state.devices.map(device=>(
    {device.title}{”“} this.addDevice(e,device.title)} />

))} {this.state.bag}

); } }

我想让它显示我一个接一个单击的所有设备,但现在单击的每个设备只会替换上一个单击的设备

问题在于您的
添加设备
方法,特别是如何创建
新数据
。您将
newData
设置为
[this.state.devices.title]
,由于
this.state.devices
是一个数组,因此没有名为
title
的属性。因此,
state.bag
的更新值将是
[未定义,数据]
,并且仅呈现为
数据
,这是最近单击的设备的标题

我认为您在这里的意思是将单击设备的标题附加到数组
state.bag
。您可以使用如下方法执行此操作:

addDevice=(e,data)=>{
控制台日志(数据);
const newBag=this.state.bag.concat(数据);
这是我的国家({
包:纽巴格
});
};
虽然更新
state.bag
的一种更好的实践方法将利用
setState
的函数形式,并且对于这类内容,扩展运算符(
)比使用
concat
更常见。此外,将
数据
重命名为更具解释性的名称(如
deviceTitle
)也会有所帮助。例如:

addDevice=(e,deviceTitle)=>{
this.setState(prevState=>({
bag:[…prevState.bag,deviceTitle],
});
}
编辑:

如果要添加将设备从
状态.bag
删除的功能,可以创建一个名为
removeDevice
的方法,并在渲染时在每个bag项目旁边添加一个按钮

例如:

removeDevice=(e,设备标题)=>{
this.setState(prevState=>({
袋:prevState.bag.filter(d=>d!==deviceTitle),
});
}
然后在渲染方法中,您将有如下内容:

    {this.state.bag.map(deviceTitle=>(
  • {deviceTitle} this.removeDevice(e,deviceTitle)}>remove
  • ))}

问题在于您的
addDevice
方法,特别是您如何创建
newData
。您将
newData
设置为
[this.state.devices.title]
,其计算结果为
[未定义]
由于
此.state.devices
是一个数组,因此没有名为
title
的属性。因此,
state.bag
的更新值将是
[未定义,数据]
,并且仅呈现为
数据,这是最近单击的设备的标题

我认为您在这里的意思是将单击设备的标题附加到数组
state.bag
。您可以使用
addDevice
方法执行此操作,如下所示:

addDevice=(e,data)=>{
控制台日志(数据);
const newBag=this.state.bag.concat(数据);
这是我的国家({
包:纽巴格
});
};
虽然更新
state.bag
的一种更好的实践方法将使用
setState
的函数形式,而且对于这类内容,扩展运算符(
)比使用
concat
更为常见。此外,还将
数据
重命名为更具解释性的内容(如
deviceTitle
)在这里可能会有所帮助。例如:

addDevice=(e,deviceTitle)=>{
this.setState(prevState=>({
bag:[…prevState.bag,deviceTitle],
});
}
编辑:

如果要添加将设备从
状态.bag
删除的功能,可以创建一个名为
removeDevice
的方法,并在渲染时在每个bag项目旁边添加一个按钮

例如:

removeDevice=(e,设备标题)=>{
this.setState(prevState=>({
袋:prevState.bag.filter(d=>d!==deviceTitle),
});
}
然后在渲染方法中,您将有如下内容:

    {this.state.bag.map(deviceTitle=>(
  • {deviceTitle} this.removeDevice(e,deviceTitle)}>remove
  • ))}
我想你很接近了。它
addDevice = (e, data) => {
  // create new copy of array from state
  const newArray = Array.from(this.state.bag);

  // push new item into array
  newArray.push(data);

  // update the state with the new array
  this.setState({
    bag: newArray
  });
}
<p>{this.state.bag.join(', ')}</p>