react hooks setData设置数据 一直被替换掉 无法追加数据

经过后续的查找资料,发现在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;
  }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hzxOnlineOk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值