因此,我正在上一门网络编程课程,在其中我们得到了这项任务,以设计一些简单的前端来订购色拉,获取所有组件等。它先前存储在.js文件中,追随时尚
let inventory = {
Sallad: {price: 10, foundation: true, vegan: true},
Pasta: {price: 10, foundation: true, gluten: true},
'Salad + Pasta': {price: 10, foundation: true, gluten: true},
'Salad + Matvete': {price: 10, foundation: true, vegan: true, gluten: true},
'Kycklingfilé': {price: 10, protein: true},
'Rökt kalkonfilé': {price: 10, protein: true},
'Böngroddar': {price: 5, extra: true, vegan: true},
'Chèvreost': {price: 15, extra: true, lactose: true},
Honungsdijon: {price: 5, dressing: true, vegan: true},
Kimchimayo: {price: 5, dressing: true},
.
.
.
};
export default inventory;
然后将其导入到我的App.js中,该App在创建react项目时创建,并作为prop发送给另一个组件,该组件负责沙拉的组成,最终将其发送回以as的形式发送道具。
所以我们现在要做的是改为从本地rest(?)服务器获取此清单。所以如果我去
http://localhost:8080/proteins
它将打开一个页面,该页面仅显示包含所有不同蛋白质选择的数组
["Kycklingfilé","Rökt kalkonfilé","Norsk fjordlax","Handskalade räkor från Smögen","Pulled beef från Sverige","Marinerad bönmix"]
然后转到
http://localhost:8080/proteins/Kycklingfilé
将为您提供另一页包含该成分属性的页面
{"price":10,"protein":true}
我试图用所有成分作为状态内部的属性重新创建库存对象是
class App extends Component {
constructor(props) {
super(props);
this.state = {
salads: [],
inventory: {
}
};
}
componentDidMount() {
const base = "http://localhost:8080/";
const pURL = base + "proteins/";
const fURL = base + "foundations/";
const eURL = base + "extras/";
const dURL = base + "dressings/";
fetch(fURL).then(response => response.json()).then(data => {
data.forEach(e => {
fetch(fURL + e).then(response => response.json()).then(data => {
Object.assign(this.state.inventory, {e : data})
})
})
});
fetch(pURL).then(response => response.json()).then(data => this.setState({data}));
fetch(eURL).then(response => response.json()).then(data => this.setState({data}));
fetch(dURL).then(response => response.json()).then(data => this.setState({data}));
}
我一直在使用
{JSON.stringify(this.state)}
尝试查看发生了什么,并使用此代码将其显示为
{"salads":[],"inventory":{},"data":["Ceasardressing","Dillmayo","Honungsdijon","Kimchimayo","Pesto","Rhodeisland","Rostad aioli","Soyavinägrett","Örtvinägrett"]}
因此,这种提取对于获取某种类型的所有成分都可以正常工作,我想这只是敷料,因为它每次都会对最后三个提取进行数据覆盖。但是问题在于库存完全是空的。
如果我改为这样写
fetch(fURL).then(response => response.json()).then(data => {
data.forEach(e => {
Object.assign(this.state.inventory, {e: fetch(fURL + e).then(response => response.json().then())})
})
});
输出变为
{"salads":[],"inventory":{"e":{}},"data":["Ceasardressing","Dillmayo","Honungsdijon","Kimchimayo","Pesto","Rhodeisland","Rostad aioli","Soyavinägrett","Örtvinägrett"]}
因此它添加了'e'对象,这是另一个问题,因为我希望它是当前元素的值,但是它完全为空,并且我不知道如何在编写时从那几秒钟获取数据这样。因此,这就是为什么它现在看起来像第一个代码段中那样,甚至在清单中都没有空的“ e”。
最后,如果我像第二个例子那样写,只是e:e像这样
fetch(fURL).then(response => response.json()).then(data => {
data.forEach(e => {
Object.assign(this.state.inventory, {e: e})
})
});
输出变为
{"salads":[],"inventory":{"e":"Salad + Quinoa"},"data":["Ceasardressing","Dillmayo","Honungsdijon","Kimchimayo","Pesto","Rhodeisland","Rostad aioli","Soyavinägrett","Örtvinägrett"]}
因此,直到代表特定类型成分的字符串数组中的.forEach似乎一切都在工作,因为它设法使用数组元素之一的值将其放入清单中的'e'。虽然它只是列表中的最后一个,但是我想这是由于这样的问题,它只是使对象为“ e”而不是当前元素的值,并覆盖每个项目。
很抱歉,如果所有杂乱无章的问题都不清楚,但是我要实现的目标是库存{}处于内部状态,看起来就像在单独文件中时的状态一样,以便在创建组件时可以发送this.state.inventory而不是导入的清单作为prop。并使用我们可以从不同页面获取的内容进行创建。
答案 0 :(得分:0)
撰写时
{e : data}
您只需创建一个新对象即可。这会将键“ e”的值设置为变量“ data”的当前值。不涉及名为“ e”的变量:
const e = 'hello';
console.log(e); // "hello"
console.log({ asd: e }); // { asd: "hello" }
console.log({ e: "asd" }); // { e: "asd" }
console.log({ e: asd }); // ReferenceError: asd is not defined
您要尝试使用的是变量e的值作为要设置的键。在javascript中,可以使用[
和]
来完成,就像这样:
const e = 'hello';
console.log({ [e]: "world" }); // { hello: "world" }
// this is necessery whenever you want a key that is not a simple word
console.log({ ["key with spaces"]: "world" }); // { "key with spaces": "world" }
console.log({ [e + e]: "world" }); // { hellohello: "world" }
编辑: 上面的代码还有另一个问题,您迟早可能会遇到:
在React中,您应该从不直接修改this.state
。务必经历this.setState()
!
https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
在您的情况下,这有点困难,因为您要发出多个请求,每个请求都会影响您状态(inventory
)中的同一键。
因为您不知道请求以什么顺序到达,以及每次新数据到达时React是否实际上会setState
还是同时全部完成,所以您不能简单地使用this.setState({ inventory: newInventory })
。相反,您应该使用here中所述的函数版本。不幸的是,这在一开始可能很难理解:(
在您的情况下,我会这样解决:
fetch(fURL).then(response => response.json()).then(data => {
data.forEach(e => {
fetch(fURL + e)
.then(response => response.json())
.then(data => this.setState((prevState) => ({
inventory: Object.assign({}, prevState.inventory, {[e]: data}),
})));
})
})
});
这里需要注意的几件事:
({
中的(prevState) => ({ ... })
:这是arrow function that returns an object this.setState
(有关详细信息,请参见上面的链接)。此函数接收当前状态作为参数(prevState
),并应返回新状态。 (尽管它可以省略保持不变的旧状态键)。这比直接将新状态传递给this.setState
更好,因为当同时发生多个setState
时,React可以按正确的顺序应用传递的函数,以使所有更改都发生,但是如果传递对象,必须决定选择其中一个对象来“赢”,以免更改丢失。Object.assign({}, prevState.inventory, {[e]: data})
中,我们无需修改prevState.inventory
,而是创建一个包含更新的广告资源的新对象。即使在this.setState中,也永远不要修改旧状态。希望这会有所帮助:)
答案 1 :(得分:0)
因此,根据@sol的建议,使用[e]为每种成分创建对象,此代码
*************
*First Title*
*************
Lots and lots and lots of text
that fill this section up
to tell you things about something
**************
*Second Title*
**************
Some Text goes here
*************
*Third Title*
*************
Lots of text goes here
with CRs etc
and tabs
现在有效。我认为为什么对我的“故障排除”而言,仅在render中打印整个状态的JSON.stringify看起来并不成功,原因是在保存代码后刷新响应时,渲染不正确。更新页面会使页面全部空白,但是通过链接单击另一个页面然后返回即可修复该页面。不知道为什么,但我会接受。