我是React /在项目中使用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>
);
}
}
我希望它显示我依次单击的所有设备,但是现在每个单击的设备都将替换之前单击的设备
答案 0 :(得分:2)
我认为你很近。看来您正在弄混devices
数组和bag
数组。
我建议使用Array.from
创建状态数组的副本。然后将新项目推入数组。 Concat用于合并两个数组。
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>
希望这会有所帮助。
答案 1 :(得分:0)
问题出在您的addDevice
方法上,尤其是您如何创建newData
。将newData
设置为[this.state.devices.title]
,由于[undefined]
是一个数组,因此没有名为this.state.devices
的属性,因此求值为title
。因此,state.bag
的更新值将为[undefined, data]
,并且仅显示为data
,这是最近单击的设备的标题。
我认为您的意思是将被点击设备的标题附加到数组state.bag
中。您可以使用addDevice
这样的方法来做到这一点:
addDevice = (e, data) => {
console.log(data);
const newBag = this.state.bag.concat(data);
this.setState({
bag: newBag
});
};
尽管更新state.bag
的一种更好的做法是利用setState
的功能形式,并且这种类型的东西比使用传播算子(...
)更为常见。 concat
。同样,将data
重命名为更具解释性的内容(例如deviceTitle
)将很有帮助。示例:
addDevice = (e, deviceTitle) => {
this.setState(prevState => ({
bag: [...prevState.bag, deviceTitle],
});
}
编辑:
如果要添加功能以从state.bag
中删除设备,可以创建一个名为removeDevice
的方法,并在渲染时在每个袋子项旁边添加一个按钮。
例如:
removeDevice = (e, deviceTitle) => {
this.setState(prevState => ({
bag: prevState.bag.filter(d => d !== deviceTitle),
});
}
然后在您的render方法中,您将得到以下内容:
<ul>
{this.state.bag.map(deviceTitle => (
<li>
<span>{ deviceTitle }</span>
<button onClick={ e => this.removeDevice(e, deviceTitle) }>remove</button>
</li>
))}
</ul>