经过后续的查找资料,发现在react hooks中setState 之所以会拿到上一次的缓存,是因为,函数在每次渲染时也是独立的(即在内存中开辟不同的空间)。这就是 Capture Value 特性。
解决办法除了以下方法之外,还有3种:https://blog.csdn.net/hzxOnlineOk/article/details/109103135
博主要实现一个分页追加数据的功能
let [childOrgList, setChildOrgList] = useState([]);
const initData = _.throttle(() => {
const option = { pid: location.state && location.state.orgId, category: location.state && location.state.category, pageNum: pageNum, pageSize: PAGESIZE };
dispatch({ type: '$/_getChildOrg', payload: option }).then((r) => {
if (r) {
isLoading = false;
const data = (r && r.list) || [];
console.log('childOrgList===>', childOrgList, data)
if (aniLoading) {
setAniLoading(false);
}
if (data && data.length < PAGESIZE) {
// 没有更多了
if (!isNoMore) {
setLoading(false);
setChildOrgList([...childOrgList, ...data]);
}
setIsNoMore(true);
} else {
pageNum += 1;
setLoading(false);
setChildOrgList([...childOrgList, ...data]);
}
} else {
setAniLoading({ aniLoading: false })
}
});
}, 1000)
但是数据一直无法追加上去!!!
经过2个小时的探索,发现,需要使用setChildOrgList(prevState => [...prevState, ...data])的形式,才能成功追加数据...
const initData = _.throttle(() => {
const option = { pid: location.state && location.state.orgId, category: location.state && location.state.category, pageNum: pageNum, pageSize: PAGESIZE };
dispatch({ type: '$/_getChildOrg', payload: option }).then((r) => {
if (r) {
isLoading = false;
const data = (r && r.list) || [];
console.log('childOrgList===>', childOrgList, data)
if (aniLoading) {
setAniLoading(false);
}
if (data && data.length < PAGESIZE) {
// 没有更多了
if (!isNoMore) {
setLoading(false);
setChildOrgList(childOrgList => [...childOrgList, ...data]);
}
setIsNoMore(true);
} else {
pageNum += 1;
setLoading(false);
setChildOrgList(childOrgList => [...childOrgList, ...data]);
}
} else {
setAniLoading({ aniLoading: false })
}
});
}, 1000)
完整代码 PartyOrgList.js
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'dva';
import { Flex, List, SearchBar, WhiteSpace, } from 'antd-mobile';
import LoadWrap from '../../components/LoadWrap';
import NavBar from '../../components/navBar';
import styles from './partyOrgList.less';
import _ from 'lodash';
import $ from 'jquery';
import { avatarUrl } from '../../utils/helper';
const PartyOrgList = props => {
let pageNum = 1;
const PAGESIZE = 15;
let height = $(document).height() - 90;
let isLoading = false;
let [pageStackIndex, setPageStackIndex] = useState(0);
let [childOrgList, setChildOrgList] = useState([]);
let [isNoMore, setIsNoMore] = useState(false);
let [loading, setLoading] = useState(false); // 用于控制分页的loading
let [aniLoading, setAniLoading] = useState(true); // 用于控制LoadWrap容器
const { location, dispatch, history } = props;
useEffect(() => {
console.log('location, history', location, history)
initData();
$('.signin_list').scroll(() => {
//已经滚动到上面的页面高度
var scrollTop = $('.signin_list').scrollTop();
// 列表容器高度
var containerHeight = $('.page_list').height();
//浏览器窗口高度
var windowHeight = $(window).height();
console.log('scrollTop, height, containerHeight', scrollTop, height, containerHeight)
//此处是滚动条到底部时候触发的事件,在这里写要加载的数据,或者是拉动滚动条的操作
if (scrollTop + height >= containerHeight - 20) { // 1页的高度 总高度 滚动高度
setLoading(true);
if (isNoMore || isLoading === true) {
return;
}
isLoading = true;
initData();
}
});
}, [location.state && location.state.category]) // 只传[] 等同于componentDidMount的效果
const initData = _.throttle(() => {
const option = { pid: location.state && location.state.orgId, category: location.state && location.state.category, pageNum: pageNum, pageSize: PAGESIZE };
dispatch({ type: '$/_getChildOrg', payload: option }).then((r) => {
if (r) {
isLoading = false;
const data = (r && r.list) || [];
console.log('childOrgList===>', childOrgList, data)
if (aniLoading) {
setAniLoading(false);
}
if (data && data.length < PAGESIZE) {
// 没有更多了
if (!isNoMore) {
setLoading(false);
setChildOrgList(childOrgList => [...childOrgList, ...data]);
}
setIsNoMore(true);
} else {
pageNum += 1;
setLoading(false);
setChildOrgList(childOrgList => [...childOrgList, ...data]);
}
} else {
setAniLoading({ aniLoading: false })
}
});
}, 1000)
// 根据不同页面设置navbar
function renderNavBar() {
return (
<div className={styles.navbarWrap}>
<NavBar title={<div className={styles.navTitle}>组织列表</div>} onLeftClick={() => props.history.replace('/')} />
</div>
);
}
function renderInit() {
// console.log('data childOrgList', childOrgList, aniLoading)
return (
<Flex direction="column" align="stretch" justify="between" className="flex100" style={{ background: '#f6f6f6' }}>
<WhiteSpace style={{ background: '#f6f6f6', height: 10 }} />
<div className="signin_list" style={{ overflow: 'auto', height: height }}>
<div className="page_list">
{
!aniLoading ? <LoadWrap data={{ data: childOrgList }} emptyString="暂无数据">
{(childOrgList && childOrgList.length && childOrgList || []).map((item, index) => {
const src = avatarUrl(item.oaCode);
const short = item.name && item.name.substring(0, 1);
return (
<List key={index} style={{ marginBottom: 8, border: 'none' }}>
<List.Item arrow="horizontal">
<div style={{ display: 'flex', flexDirection: 'row' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<span style={{
fontSize: 16, color: '#333', lineHeight: '20px',
// overflow: 'hidden',
// textOverflow: 'ellipsis',
// display: '-webkit-box',
// webkitLineClamp: '2',
// webkitBoxOrient: 'vertical',
}}>{item}</span>
</div>
</div>
</List.Item>
</List>
)
})}
{loading && !isNoMore ? (
<div style={{ padding: '15px 0', fontSize: 14, color: '#999', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span className="am-activity-indicator-spinner" style={{ width: 15, height: 15 }} />
<span style={{ marginLeft: 5, }}>正在加载</span>
</div>) : null
}
{isNoMore && childOrgList && childOrgList.length > PAGESIZE ? <div style={{ padding: '15px 0', fontSize: 14, color: '#999', textAlign: 'center' }}>没有更多了</div> : null}
</LoadWrap> : <div className={styles.spinner} style={{ position: 'relative' }} />
}
</div>
</div>
</Flex>
);
}
return (
<Flex
direction="column"
align="stretch"
className="flex100"
style={{ backgroundColor: '#F6F6F6' }}
>
{renderNavBar()}
<Flex.Item
className={`flex100 ${styles.content}`}
style={{ height: 'auto', overflow: 'hidden' }}
>
{renderInit()}
</Flex.Item>
</Flex>
);
}
function mapStateToProps(state, ownProps) {
// const data = state.signIn;
return {
// childOrgList: data.childOrgList,
};
}
export default connect(mapStateToProps)(PartyOrgList);
partyOrgList.less
.signWrap {
height: 70px;
padding: 0 15px;
background: #6ba3f1;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.spinner {
margin: 5rem auto;
width: 2rem;
height: 2rem;
position: relative;
background: center center/100% 100% no-repeat
url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTMxMzYwMzgzNjkyIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjczMTAiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNMTAyMy40MjgyMTkgNDg4LjM2NDE4N2E1MTEuOTgyMjM0IDUxMS45ODIyMzQgMCAxIDAtNDg3Ljc2NTQ3NCA1MzUuMDcyNjMzIDUxMS45ODIyMzQgNTExLjk4MjIzNCAwIDAgMCA0ODcuNzY1NDc0LTUzNS4wNzI2MzNNNjMuMjA1NTM5IDY5MC4xODc1ODNhNDgwLjgwMjUxNiA0ODAuODAyNTE2IDAgMCAxLTMzLjQ4MzYzOC0xNTUuNzk2MTk0cS0wLjUxMTk4Mi0xMS4zNjYwMDYtMC41MTE5ODItMjIuNzMyMDExQTQ4Mi44NTA0NDUgNDgyLjg1MDQ0NSAwIDAgMSA0ODkuNjM1NTQyIDI5LjgzMjg5OGM3LjYyODUzNS0wLjQwOTU4NiAxNS4zNTk0NjctMC41MTE5ODIgMjIuNjgwODEzLTAuNTExOTgzYTQ4MS4yNjMzIDQ4MS4yNjMzIDAgMCAxIDMyOS4yNTU3NzUgMTMwLjE0NTg4NEM3OTcuNDM5MjYxIDE5MS43MjE2OCA3MjcuMDQxNzA0IDIzOS4wMjg4MzggNjUwLjI0NDM2OSAyNzAuNjE4MTQyYzEwLjIzOTY0NS00MS4yNjU3NjggMTguNDgyNTU5LTc0LjAzMjYzMSAxOC41MzM3NTctNzQuMzM5ODJhMTQuODQ3NDg1IDE0Ljg0NzQ4NSAwIDAgMC0xOS4yNTA1MzItMTguNzM4NTVoLTAuMzU4Mzg4YTcuMDY1MzU1IDcuMDY1MzU1IDAgMCAwLTEuODQzMTM2IDAuNzY3OTc0Yy0zLjQ4MTQ3OSAxLjQzMzU1LTExNi45MzY3NDIgOTIuNDYzOTkxLTIyNy4wNjQxMjEgMTM4LjY0NDc4OSAxMC4yMzk2NDUtNDAuMzQ0MiAxOS42NjAxMTgtNzguNzk0MDY2IDE5LjcxMTMxNi03OS4xNTI0NTRBMTAuNTQ2ODM0IDEwLjU0NjgzNCAwIDAgMCA0NDAuMzMxNjUzIDIzNS41NDczNTl2LTAuODE5MTcxYTcuNDc0OTQxIDcuNDc0OTQxIDAgMCAwIDAtMS42MzgzNDN2LTAuODcwMzdBMTMuNzcyMzIyIDEzLjc3MjMyMiAwIDAgMCA0MzMuMTYzOTAxIDIyMC4xODc4OTJjLTAuNTYzMTggMC0xLjE3NzU1OS0wLjU2MzE4LTEuNzQwNzM5LTAuNzY3OTczYTEwLjkwNTIyMiAxMC45MDUyMjIgMCAwIDAtMS44NDMxMzYtMC41NjMxODEgMTQuNTkxNDk0IDE0LjU5MTQ5NCAwIDAgMC0xMS4zNjYwMDYgMS44NDMxMzdjLTEwLjIzOTY0NSA3LjY3OTczNC0xMDcuMDA0Mjg3IDkwLjQ2NzI2MS0yMjUuOTg4OTU4IDE0MC41OTAzMjEgMCAwLTE0LjI4NDMwNCA1Ny45MDUxOTEtMTQuNzQ1MDg4IDU5LjU0MzUzNGw0MC40OTc3OTQtOC4xNDA1MThhMjIuNDI0ODIyIDIyLjQyNDgyMiAwIDAgMSAyMS41MDMyNTQgOC44NTcyOTNjMC40NjA3ODQgMC43Njc5NzMgMC45MjE1NjggMS41ODcxNDUgMS4zMzExNTQgMi4zNTUxMThhNy43ODIxMyA3Ljc4MjEzIDAgMCAwIDAuNTExOTgyIDEuMjI4NzU4IDE0LjAyODMxMyAxNC4wMjgzMTMgMCAwIDEgMC42NjU1NzcgMS44OTQzMzQgMjYuMDU5ODk2IDI2LjA1OTg5NiAwIDAgMS0wLjY2NTU3NyAxMy4zMTE1MzhjLTUuMTE5ODIyIDIwLjQ3OTI4OS02Mi4zMDgyMzggMjU5LjQ3MjU5Ni02My4zMzIyMDIgMjYzLjgyNDQ0NS00MS43Nzc3NS0zLjEyMzA5Mi03Ni43OTczMzUtNy45MzU3MjUtMTE0Ljc4NjQxNy0xNC4wNzk1MTFtNjMzLjg4NTIwNC0zMjUuMzY0NzFhNS43ODUzOTkgNS43ODUzOTkgMCAwIDEgMCAwLjk3Mjc2NiAxNi4wNzYyNDIgMTYuMDc2MjQyIDAgMCAxLTAuMzA3MTg5IDEuNjM4MzQzYzAgMS4wNzUxNjMtNzUuNTE3MzggMzE1Ljg0MTg0LTc1Ljc3MzM3MSAzMTcuMTIxNzk2LTI1LjI0MDcyNCAzLjczNzQ3LTUwLjY4NjI0MSA2Ljg2MDU2Mi03Ni4yMzQxNTUgOS42NzY0NjQgNi42NTU3NjktMjYuNjc0Mjc0IDY3LjQyODA2LTI3MC42MzM4MDkgODYuMDY0MjE0LTM0NS40MzQ0MTNsNDUuNzIwMDEzLTcuMDY1MzU1YTE2Ljc0MTgxOSAxNi43NDE4MTkgMCAwIDEgMi4zNTUxMTkgMCA5LjA2MjA4NiA5LjA2MjA4NiAwIDAgMSAxLjg0MzEzNiAwIDIyLjI3MTIyNyAyMi4yNzEyMjcgMCAwIDEgMTMuNDY1MTMzIDkuMjY2ODc5IDIxLjM0OTY1OSAyMS4zNDk2NTkgMCAwIDEgMi45Njk0OTcgMTMuMjYwMzRNNDY5LjIwNzQ1MSA0MDQuNTAxNDk3Yy0xLjUzNTk0NyA2LjI5NzM4MS01OC43MjQzNjIgMjQyLjkzNTU3LTcyLjc1MjY3NiAzMDEuMTQ3OTUtMjQuNzI4NzQyIDAuOTcyNzY2LTQ5LjE1MDI5NCAxLjU4NzE0NS03My41MjA2NDkgMS45NDU1MzIgMjEuMTk2MDY0LTg0Ljc4NDI1OCA1NC45ODY4OTItMjIwLjYxMzE0NSA4MC44NDE5OTUtMzI0LjM5MTk0MyAwIDAgNDQuMjg2NDYzLTYuODA5MzY0IDQ0Ljg0OTY0NC02LjgwOTM2NGEyMS4xOTYwNjQgMjEuMTk2MDY0IDAgMCAxIDIwLjQ3OTI4OSAyOC4xMDc4MjVtNjUuMDIxNzQ0IDU4OS45NTcxMjhjLTcuNjI4NTM1IDAtMTUuMzU5NDY3IDAuNDYwNzg0LTIyLjczMjAxMSAwLjQ2MDc4NGE0ODEuNjcyODg2IDQ4MS42NzI4ODYgMCAwIDEtMzUxLjIxOTgxMy0xNTIuMDU4NzIzYzM2NC4wMTkzNjktOS40NzE2NzEgNjI1Ljg5ODI4MS04Mi45OTIzMiA4MDQuNTI4ODgzLTE2My44MzQzMTVhNDgzLjA1NTIzOCA0ODMuMDU1MjM4IDAgMCAxLTQzMC43MzA2NTQgMzE1LjM4MTA1Nm00NTQuNjQwMjI0LTQwNy4xNzk0NzFBMTY0Ny4zNTQwMzcgMTY0Ny4zNTQwMzcgMCAwIDEgNzczLjEyMDEwNSA2NTYuMzk2NzU2YzI0LjE2NTU2MS05Ny4yNzY2MjUgODMuNjA2Njk5LTMzNC42MzE1ODggMTEyLjM4MDEtNDQ5Ljk4MTE4NmE0ODAuMDg1NzQxIDQ4MC4wODU3NDEgMCAwIDEgMTA4LjY5MzgyOSAyODMuNDMzMzY1YzAuMzU4Mzg4IDcuNTc3MzM3IDAuNTExOTgyIDE1LjM1OTQ2NyAwLjUxMTk4MiAyMi42ODA4MTNhNDkwLjAxODE5NiA0OTAuMDE4MTk2IDAgMCAxLTUuNzM0MjAxIDc0Ljc0OTQwNiIgZmlsbD0iI2NjY2NjYyIgcC1pZD0iNzMxMSI+PC9wYXRoPjwvc3ZnPg==');
}
.spinner::before {
top: 0;
left: 0;
content: '';
width: 100%;
height: 100%;
position: absolute;
animation: rotates 1s linear infinite;
background: center center/100% 100% no-repeat
url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTMxMzYwNjEzMDkwIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9Ijc1MjUiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNODUyLjE3MjY2NCAxNzEuODI3NTQxbDIxLjg2MjM5MS0yMS44NjIzOTFBNTEwLjQxMjU5NiA1MTAuNDEyNTk2IDAgMCAwIDUxMiAwLjAwMDQxdjMwLjcxOTk4N2E0NzkuNzk1MDA4IDQ3OS43OTUwMDggMCAwIDEgMzQwLjE3MjY2NCAxNDEuMTA3MTQ0eiIgcC1pZD0iNzUyNiIgZmlsbD0iI0JGODMyRSI+PC9wYXRoPjwvc3ZnPg==');
}
.avatar {
width: 40px;
height: 40px;
display: inline-block;
// margin-bottom: 5px;
border-radius: 50%;
background-color: #d8be85;
color: #fff;
}
.avatarImg {
width: 40px !important;
height: 40px !important;
border-radius: 50%;
}
.avatar em {
font-style: normal;
font-size: 15px;
line-height: 41px;
color: #fff !important;
}
.user {
text-align: center;
width: 55px;
}
.user .name {
font-size: 12px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
:global {
.am-search {
background: #fff;
border-bottom: 1px solid #ddd;
}
.am-search-input {
background: #f7f7f7;
}
.am-search-cancel {
color: #999;
}
}
@keyframes rotates {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@media screen and (max-width: 380px) {
.navTitle {
font-size: 16px;
}
}
@media screen and (max-width: 350px) {
.navTitle {
font-size: 14px;
}
}