我正在尝试在 React 中构建一个信息面板,显示在线社区的三项最新活动。主要是最新注册社区的人。
我目前有一个最新 30 个注册的列表,作为 JSX 组件数组从 API 调用加载到 dataArr 常量中。然后,我有一个进一步的 useEffect,它是由 dataArr 常量的更新触发的,该常量将 dataArr 中的最后 3 项保存到进一步的数组常量调用结果中。然后,它会以包含 3 项的列表的形式显示在屏幕上。
这工作正常,但我的下一步是将 dataArr 修剪 1 个项目(数组中的最后一个项目),以便显示自动更新以丢失 3 列表中的最后一个项目并获得一个新项目。然后我将添加一个漂亮的动画过渡效果,以便用户可以看到正在发生的事情。
我创建了一个测试来确保逻辑有效 - testAction - 这是从添加到 JSX 元素之一的 onClick 操作调用的,这就是我遇到麻烦的地方。 testAction 函数中的 dataArr 常量显示为空。它已丢失数据。
我添加了一个新的返回页面,该页面具有硬编码的 JSX 元素,而不是从数组写入的元素,并且当我从静态返回调用 testAction 函数时,dataArr 中的值仍然存在。然而,当从实际返回(从包含动态生成的基于数组的 JSX 的“结果”常量生成的返回)调用它时,dataArr 变量始终为空。
我最终想使用 setInterval() 以 10 秒的间隔运行 testAction 代码,当我再次尝试从 setInterval() 执行代码时,dataArr 常量为空。
是什么导致 dataArr 常量丢失数据?跟我把 JSX 代码写进数组有关系吗?
如有任何建议,我们将不胜感激。
import React, { createRef, forwardRef, useEffect, useState } from 'react'
import { Link, withRouter } from 'react-router-dom'
import { withAuth } from '../../AuthContext'
import {
Title,
PrimaryOutlineButton,
SubtitleOpen,
} from '../../Utils/CustomClasses'
import styled from 'styled-components'
const LatestActivityWrapper = styled.div`
margin: 0 0 40px 0;
`
const LatestActivityTitle = styled(Title)`
font-size: 18px !important;
`
const ActivityName = styled.div`
display: flex;
gap: 5px;
flex-wrap: nowrap;
`
const BreakSub = styled(SubtitleOpen)`
display: flex;
overflow-wrap: anywhere;
font-color: #941e15 !important;
font-family: 'Open Sans', sans-serif;
font-size: 18px;
font-weight: 400;
margin: 4px 0 0 0;
`
const BreakSubActivity = styled(BreakSub)`
width: 125px;
font-weight: 300;
font-size: 16px;
b {
font-weight: 600;
}
`
const BreakSubActivityRight = styled(BreakSubActivity)`
font-size: 16px;
width: -webkit-fill-available;
`
const ActivityText = styled(SubtitleOpen)`
font-family: 'Open Sans', sans-serif;
font-size: 16px;
font-weight: 300;
margin: 8px 0 0;
`
const LatestActivity = () => {
const [dataArr, setDataArr] = useState([])
const [results, setResults] = useState('')
const [test, setTest] = useState('')
useEffect(() => {
axios
.get(`/api/XXXXXXXXXXXXXXX/latestactivity`)
.then((response) => {
setTest('test text')
setDataArr(
response.data.map((d, index) => {
return (
<LatestActivityComponent
ref={createRef()}
key={index}
u={d.forename}
country={d.country.nicename}
activityType={'SIGNUP'}
color={'#3DBD7E'}
activityText={
d.forename + ' signed up from ' + d.country.nicename
}
/>
)
})
)
})
.catch((err) => {
console.log('Error getting latest featured activity: ', err)
})
}, [])
useEffect(() => {
console.log('dataArr: ' + JSON.stringify(dataArr))
setResults(dataArr.slice(dataArr.length - 3, dataArr.length))
}, [dataArr])
const testAction = () => {
console.log('testAction....')
console.log('test: ' + test)
console.log('dataArr: ' + dataArr)
console.log('test: ' + test)
console.log('dataArr.length: ' + dataArr.length)
const newData = dataArr.pop()
console.log('dataArr.length: ' + dataArr.length)
console.log('dataArr: ' + dataArr)
setDataArr(dataArr)
}
const LatestActivityComponent = forwardRef(
({ u, country, activityType, color, activityText }, ref) => {
return (
<LatestActivityWrapper ref={ref}>
<LatestActivityTitle color={color} size="18px">
{activityType}
</LatestActivityTitle>
<ActivityName>
<BreakSubActivity onClick={() => testAction()}>
<b>Name:</b>
</BreakSubActivity>
<BreakSubActivityRight>{u}</BreakSubActivityRight>
</ActivityName>
<ActivityName>
<BreakSubActivity>
<b>Location:</b>
</BreakSubActivity>
<BreakSubActivityRight>{country}</BreakSubActivityRight>
</ActivityName>
<ActivityText>{activityText}</ActivityText>
</LatestActivityWrapper>
)
}
)
if (!results || test == '') {
return (
<div className="card-body text-center">
<div
className="spinner-border homestays-spinner"
style={{ margin: '100px auto 100px', opacity: '0.3' }}
role="status"
></div>
</div>
)
}
// The testAction function does not work from here
//return results
// The testAction function works from here
return (
<BreakSubActivity onClick={() => testAction()}>
aaa - {test}
</BreakSubActivity>
)
}
export default withRouter(withAuth(LatestActivity))
dataArr.pop()
会改变 dataArr。可以用slice(0, -1)
代替;它返回原始数组的副本,没有最后一个元素。
testAction
的最小版本可以如下所示:
const testAction = () => {
setDataArr(prev => prev.slice(0, -1))
}