组件填充后没有任何东西出现
客户:React,MOBX 服务器:nodejs,mongodb
简短问题:
我有一系列元素填充在使用效果函数内,预期结果:应渲染数组的每个元素,实际结果:什么也没有发生。仅在VSCODE中的代码更改后才出现渲染。
尝试:将.map更改为.foreach,setState(... [arr])中的传播运算符的不同变化,甚至没有传播操作员,什么也不会改变。
信息:
friends.jsx部分,包含数组状态及其连接的所有内容,也包含填充功能。
const [requestsFrom, setRequestsFrom] = useState([]) //contains id's (strings) of users that will be found in MongoDB
const [displayRequestsFrom, setDisplayRequestsFrom] = useState([]) //should be filled by elements according to requestsFrom, see below
const getUsersToDisplayInFriendRequestsFrom = () => {
const _arr = [...displayRequestsFrom]
requestsFrom.map(async(f) => {
if (requestsFrom.length === 0) {
console.log(`empty`) //this part of code never executes
return
} else {
const _candidate = await userPage.fetchUserDataLite(f)
_arr.push( //template to render UserModels (below)
{
isRequest: true,
link: '#',
username: _candidate.login,
userId: _candidate._id
}
)
console.log(_arr)
}
})
setDisplayRequestsFrom(_arr)
// console.log(`displayRequestsFrom:`)
console.log(displayRequestsFrom) //at first 0, turns into 3 in the second moment (whole component renders twice, yes)
}
渲染模板函数:
const render = {
requests: () => {
return (
displayRequestsFrom.map((friendCandidate) => {
return (
<FriendModel link={friendCandidate.link} username={friendCandidate.username} userId={friendCandidate.userId}/>
)
})
)
}
}
使用效果:
useEffect(() => {
console.log(`requestsFrom.length === ${requestsFrom.length}`)
if (!requestsFrom.length === 0) {
return
} else if (requestsFrom.length === 0) {
setRequestsFrom(toJS(friend.requests.from))
if (toJS(friend.requests.from).length === 0) {
const _arr = [...requestsFrom]
_arr.push('0')
setRequestsFrom(_arr)
}
}
if (displayRequestsFrom.length < 1 && requestsFrom.length > 0) {
getUsersToDisplayInFriendRequestsFrom()
//displayRequestsFrom and requestsFrom lengths should be same
}
},
[requestsFrom]
)
JSX的一部分with Rendering:
<div className={styles.Friends}>
<div className={styles['friends-container']}>
{render.requests()}
</div>
</div>
upd:我的console.log从开始时以正确的顺序输出:
requestsFrom.length === 0
requestsFrom.length === 3
displayRequestsFrom === 0
displayRequestsFrom === 3
正如我们所能看到的,也不是从displayrequestsss安装和渲染的末尾,displayRequestsss neseversequestsss explaysRequestssss explaysrequestssss explayrequestssss唯一的displayrequestssss我找不到的问题 - 为什么在DisplayRequestsss中的3个模板也不会渲染它们,但是如果我按下forceupdate按钮(为调试目的而创建它,则在这里是:)
const [ignored, forceUpdate] = React.useReducer(x => x + 1, 0);
<button onClick={forceUpdate}>force update</button>
Client: React, mobx
Server: NodeJS, MongoDB
Short question:
I have an array of elements which fills inside of useEffect function, expected result: each element of array should be rendered, actual result: nothing happens. Render appears only after code changing in VSCode.
Tried: changing .map to .forEach, different variations of spread operator in setState(...[arr]) or even without spread operator, nothing changes.
Info:
Friends.jsx part, contains array state and everything that connected with it, also the fill-up function.
const [requestsFrom, setRequestsFrom] = useState([]) //contains id's (strings) of users that will be found in MongoDB
const [displayRequestsFrom, setDisplayRequestsFrom] = useState([]) //should be filled by elements according to requestsFrom, see below
const getUsersToDisplayInFriendRequestsFrom = () => {
const _arr = [...displayRequestsFrom]
requestsFrom.map(async(f) => {
if (requestsFrom.length === 0) {
console.log(`empty`) //this part of code never executes
return
} else {
const _candidate = await userPage.fetchUserDataLite(f)
_arr.push( //template to render UserModels (below)
{
isRequest: true,
link: '#',
username: _candidate.login,
userId: _candidate._id
}
)
console.log(_arr)
}
})
setDisplayRequestsFrom(_arr)
// console.log(`displayRequestsFrom:`)
console.log(displayRequestsFrom) //at first 0, turns into 3 in the second moment (whole component renders twice, yes)
}
Render template function:
const render = {
requests: () => {
return (
displayRequestsFrom.map((friendCandidate) => {
return (
<FriendModel link={friendCandidate.link} username={friendCandidate.username} userId={friendCandidate.userId}/>
)
})
)
}
}
useEffect:
useEffect(() => {
console.log(`requestsFrom.length === ${requestsFrom.length}`)
if (!requestsFrom.length === 0) {
return
} else if (requestsFrom.length === 0) {
setRequestsFrom(toJS(friend.requests.from))
if (toJS(friend.requests.from).length === 0) {
const _arr = [...requestsFrom]
_arr.push('0')
setRequestsFrom(_arr)
}
}
if (displayRequestsFrom.length < 1 && requestsFrom.length > 0) {
getUsersToDisplayInFriendRequestsFrom()
//displayRequestsFrom and requestsFrom lengths should be same
}
},
[requestsFrom]
)
Part of jsx with rendering:
<div className={styles.Friends}>
<div className={styles['friends-container']}>
{render.requests()}
</div>
</div>
UPD: my console.log outputs in the right order from beginning:
requestsFrom.length === 0
requestsFrom.length === 3
displayRequestsFrom === 0
displayRequestsFrom === 3
As we can see, nor requestsFrom, neither displayRequestsFrom are empty at the end of the component mounting and rendering, the only problem left I can't find out - why even with 3 templates in displayRequestsFrom component doesn't render them, but render if I press forceUpdate button (created it for debug purposes, here it is:)
const [ignored, forceUpdate] = React.useReducer(x => x + 1, 0);
<button onClick={forceUpdate}>force update</button>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Pricipal回答
这里的问题是您正在执行.map方法内部的获取。
这样,您就不会等待获取完成(请参见评论)
错误的示例(带有澄清评论)
要解决,您需要等待每个获取,然后再使用新数组更新状态。
为此,您的整个功能必须是异步的,并且您需要在循环中等待。
例如,此代码变成
一样并行执行每个
您也可以像其他问题
从未调用服务的
问题,似乎您正在映射您试图调用服务的空数组。
如果数组(From)为空的数组(requestssfrom)(在USESTATE([])中初始化您在MAP方法中传递的函数永远不会被调用。
不确定您要确切地尝试做什么,但这应该是问题之一...
不要使用状态作为渲染组件
,您不使用状态来存储渲染的组件
,而是应该将数据映射在模板,然后为数据阵列中的每个元素提供一个组件。
例如:
不:
不要使用
useffect
来初始化您的状态,我想知道为什么您在
value useffect 中设置
requests
。您为什么不在
usestate()
内初始化requests
的状态?类似的东西,
而不是检查
useffect
内的长度并填写,以便您的使用效率可以变成类似的东西
PRICIPAL ANSWER
The problem here is that you are executing fetch inside .map method.
This way, you are not waiting for the fetch to finish (see comments)
Wrong Example (with clarification comments)
To solve, you need to await for each fetch before updating the state with the new array.
To do this, your entire function has to be async and you need to await inside a for loop.
For example this code became
You can also execute every fetch in parallel like this
Other problems
Never Calling the Service
Seems you are mapping on an empty array where you are trying to call your service.
If the array (requestsFrom) is empty ( as you initialized in the useState([]) ) the function you pass in the map method is never called.
Not sure what you are exactly trying to do, but this should be one of the problems...
Don't use state for rendered components
Also, you shoudn't use state to store rendered components
, instead you should map the data in the template and then render a component for each element in your data-array.
For example:
Not:
Don't use
useEffect
to initialize your stateI'm wondering why you are setting the
requestsFrom
value inside theuseEffect
.Why aren't you initializing the state of your
requestsFrom
inside theuseState()
?Something like
instead of checking the length inside the
useEffect
and fill itSo that your useEffect can became something like this