javascript - ReactJS 在接收到要渲染的数据之前调用渲染方法
问题描述
当主组件加载时,我向我的 API 发送一个 GET 请求,以获取在名为 的字段中具有特定值的所有对象"ship_name"
,这意味着可能会到达更多“构建”,因此将有更多需要渲染。加载主组件后,我在同一个文件中创建了第二个组件,称为“Builds”。作为道具,我向这个组件发送对象数组 this.state.builds。
更好的解释:
- 用户在搜索栏中插入“ship_name”
- API 查找具有该“ship_name”的所有构建
- 所有构建都发送到子组件
- 使用“gears”(齿轮名称)API 查找文件名并将其发送回
- !在链接到达之前反应渲染
<Builds builds={this.state.builds} />
“构建”的结构是这样的
[
{
"gears": [
"Triple 410mm (10th Year Type Prototype)",
"Triple 155mm (3rd Year Type)",
"Twin 40mm Bofors STAAG Mk II",
"High Performance Fire Control Radar",
"Type 1 Armor Piercing Shell"
],
"rarities": [
"o",
"o",
"o",
"o",
"o"
],
"_id": "5eac7b450e64096b082f4c43",
"ship_name": "Gascogne",
"pv": "e"
},
{
"gears": [
"Triple 410mm (10th Year Type Prototype)",
"Triple 155mm (3rd Year Type)",
"Twin 40mm Bofors STAAG Mk II",
"High Performance Fire Control Radar",
"Type 1 Armor Piercing Shell"
],
"rarities": [
"o",
"o",
"o",
"o",
"o"
],
"_id": "5f131d6e2e3f16ef3de48e4f",
"ship_name": "Gascogne",
"pv": "e"
}
]
到目前为止一切正常。
render() {
return (
this.props.builds.map((build) => (
<div className="container" key={uuidv4()}>
<img src={"/img/gears/" + this.getGearData(build.gears[0])} className={build.rarities[0] + " gI g1"}></img><div className={"t t1"}>{build.gears[0]}</div>
<img src={"/img/gears/" + this.getGearData(build.gears[1])} className={build.rarities[1] + " gI g2"}></img><div className={"t t2"}>{build.gears[1]}</div>
<img src={"/img/gears/" + this.getGearData(build.gears[2])} className={build.rarities[2] + " gI g3"}></img><div className={"t t3"}>{build.gears[2]}</div>
<img src={"/img/gears/" + this.getGearData(build.gears[3])} className={build.rarities[3] + " gI g4"}></img><div className={"t t4"}>{build.gears[3]}</div>
<img src={"/img/gears/" + this.getGearData(build.gears[4])} className={build.rarities[4] + " gI g5"}></img><div className={"t t5"}>{build.gears[4]}</div>
</div>
))
)
}
/*------------------------------*/
getGearData(gear_name) {
let requestString = encodeURI('http://localhost:5000/gears/one?q=' + gear_name)
let data;
Axios.get(requestString)
.then(res => {
console.log(res.data[0].image_link)
data = res.data[0].image_link
})
return data
/* what */
}
这里发生的是,在我渲染的同时,我试图获取图像的 URL。GET 方法有效,实际上 console.log 打印文件的实际名称
32200.png gear.component.js:76
26600.png gear.component.js:76
1260.png gear.component.js:76
600.png gear.component.js:76
34180.png gear.component.js:76
但在 SRC 上,结果是"/img/gears/undefined"。我无法理解的一件事是为什么所有结果都打印了 2 次,但这并不是什么大问题,因为最终这些东西只能正确渲染一次。
我尝试过使用许多方法、状态、Promises(即使我还没有真正理解它们是如何工作的),这是我第一次真正陷入这样的困境。事实上,主要组件使用“ship_name”来获取“ship_icon”和“faction_icon”的文件名,这没有问题,可能是因为我使用了那里的状态。
这是一个关于它现在的样子的想法
这是一个关于它应该是什么样子的想法
我曾经使用 php 和 SQL 完成了这个个人项目,现在我正在尝试使用 React 和 MongoDB 来完成。
解决方案
注意:您应该首先在检索和/或设置构建的过程中调用获取图像 URL,这种数据结构是设计不佳的标志;现在,那说:
React 是一个反应式库。它只对正在监视的数据的变化做出反应。
您不能混合使用异步和同步函数并期望一切都等待。
当你打电话给这里时,这是按发生顺序发生的getGearData(gear_name)
事情的粗略概述
- 你
getGearData
用变量调用gear_name
- 一个可修改的变量
requestString
被声明并设置为encodeURI('http://localhost:5000/gears/one?q=' + gear_name)
(旁注,这应该是const
因为它没有被修改 data
声明了一个可修改的变量- 启动异步请求以从服务器检索数据
- 对 的当前值的引用
data
返回给调用者 - 反应渲染
- 您的请求完成
- 局部变量在函数范围内
data
设置
你必须等待异步操作
有很多方法可以做到这一点。这是使用占位符图像的示例
const placeholder = "https://link.to/placeholder-image.png"
class MyComponent extends Component {
constructor(props) {
super(props)
this.state = { images: {} }
}
componentDidUpdate(prevProps) {
if(prevProps.builds != this.props.builds) {
this.fetchImages()
}
}
fetchImages() {
this.props.builds.forEach(build => {
build.gears.forEach(gear => {
Axios.get(encodeURI('http://localhost:5000/gears/one?q=' + gear_name))
.then(res => {
const link = res.data[0].image_link
console.log(link)
this.setState(state => { images: { ...state.images, [gear]: link } })
})
})
})
}
mapGears = (gears) =>
gears.map(
(gear, i) =>
<img
src={this.state.images[gear] || placeholder}
className={`t t${i}`}
key={`${gear}.${i}`}
/>
)
render() {
return (
this.props.builds.map((build) => (
<div className="container" key={build._id}>
{this.mapGears(build.gears)}
</div>
))
}
}
推荐阅读
- javascript - 在 Css 中堆叠多个相同类型的转换
- python - 为一系列数字着色
- visual-studio - Visual Studio 2019 SQL 报告服务 - 单击预览选项卡时打开另存为窗口
- python - 如何交叉 listA.txt 和 listB.txt 的行并返回一个 output.txt,其中 listB.txt 的每一行在 Python 和 grep 中匹配?
- openstreetmap - 与 olms 一起使用时,OpenLayers t.getScaleArray 不是函数
- primefaces - RemoteCommand,不在primefaces中发送参数
- sql - 如何优化 1000 条 sql 查询以进行更新?
- java - 我的 Spring-Boot 自定义登录表单不工作 [更新]
- excel - Excel VBA 数组公式使用索引匹配给出错误类型不匹配
- html - 有什么方法可以确保这个线性渐变上的所有条纹都是相同的大小?