2021-04-17 the use method of hooks listView long list in antd moblie, enter the error reporting dataSource for the second time, and report the error must be the same

Official usage (custom container) https://mobile.ant.design/components/list-view-cn/#components-list-view-demo-basic-sticky
The official method of use is very smooth at first glance, but there will be some unexpected problems as soon as the data is put on. I have deep experience

At first glance, some friends may not understand the meaning of officially rendered sectionIDs, rowIDs and datablocks. In fact, they don't need to understand what they mean. As long as our own data corresponds to the officially created key, there will be no problem.
How exactly?

This commentary corresponds to 1:

Set NUM_SECTIONS is changed to the number of data you also get each time, and I get 10 data per page,
If 10 entries are enough for you to fill a whole page, then num_ ROWS_ PER_ If the section is changed to 1, I'll fill a whole page, and I'll change to 1,
After these changes, we don't need to worry about the automatic generation of key s by components. We just need to integrate the data together. See 2 for how to integrate the data
Change pageSize={4} in the official website to our 10

1. Here are the official usage and configuration change methods:

    const NUM_SECTIONS = 5;  //Number of entries per page
    const NUM_ROWS_PER_SECTION = 5;  //Render several times} why render many times? Because if there is less than one page when loading for the first time, the drop-down will not trigger the loading of data.
    let pageIndex = 0;

    const dataBlobs = {};
    let sectionIDs = [];
    let rowIDs = [];
    function genData(pIndex = 0) {
        for (let i = 0; i < NUM_SECTIONS; i++) {
        const ii = (pIndex * NUM_SECTIONS) + i;
        const sectionName = `Section ${ii}`;
        dataBlobs[sectionName] = sectionName;
        rowIDs[ii] = [];

        for (let jj = 0; jj < NUM_ROWS_PER_SECTION; jj++) {
          const rowName = `S${ii}, R${jj}`;
          dataBlobs[rowName] = rowName;
      sectionIDs = [...sectionIDs];
      rowIDs = [...rowIDs];

2. I changed the official class component into hooks component

    const [dataSourceAll, setdataSourceAll] = useState([]);  //Store the last acquired data in order to determine whether to continue to request data later. Stop requesting data if the length is 0
    const [dataSourcenew, setdataSourcenew] = useState([]);   //Store the original data and merge the new data.
    const getList=()=>{
         let dataSources=[]  //Newly acquired data
         setdataSourceAll(dataSources);  //Put the newly requested data into
         setdataSourcenew([...dataSourcenew, ...dataSources])  //Merge the new data with the original data.
          getList()  //get data
    // This method obtains data for drop-down
    const onEndReached = async (event) => {
        // Judge whether there is data in the obtained data here. If it is not proved that it has reached the last page, it will not obtain the data.
        if (dataSourceAll.length > 0) {
            getList()  //get data
            // Every time you get data, you need to add it to the original key
            setdataSource(dataSource.cloneWithRowsAndSections(dataBlobs, sectionIDs, rowIDs))
            // Call the party adding the key (adding the key refers to the official gendata (method))
            // In the official way, we call the getData method first, but because of the asynchronous problem, we need to call the genData method later.

Well, now that the data has been sorted out, how to render it?

The data in the official website is the simulated static data in the official website. We only need to replace the static data with our own data after successful integration, and replace the data in it (data refers to the static data in the official website), because we have passed setdatasourcenew ([... Datasourcenew,... Datasources]) in 2
Integrate the data together, so now replace the data with dataSourcenew.

    //Official website:
    let index = data.length - 1;
    //After replacement:
    let index = dataSourcenew.length - 1;
    const row = (rowData, sectionID, rowID) => {
      if (index < 0) {
        //Official website:
        index = data.length - 1;
        //After replacement:
        index = dataSourcenew.length - 1;
      //Official website:
      const obj = data[index--];
      //After replacement:
      const obj = dataSourcenew[index--];
      return (
        <div key={rowID} style={{ padding: '0 15px' }}>
              lineHeight: '50px',
              color: '#888',
              fontSize: 18,
              borderBottom: '1px solid #F6F6F6',
          <div style={{ display: '-webkit-box', display: 'flex', padding: '15px 0' }}>
            <img style={{ height: '64px', marginRight: '15px' }} src={obj.img} alt="" />
            <div style={{ lineHeight: 1 }}>
              <div style={{ marginBottom: '8px', fontWeight: 'bold' }}>{obj.des}</div>
              <div><span style={{ fontSize: '30px', color: '#FF6E27' }}>35</span>¥ {rowID}</div>

Now the data has been rendered into your dom, but if you switch the page, the word must be the same will appear because we have defined the initial value externally

    let pageIndex = 0;
    const dataBlobs = {};
    let sectionIDs = [];
    let rowIDs = [];

We only need to reset these four initial values. Here is how hooks manually resets the initial values


    useEffect(() => {
        // Manually reset the field to prevent errors in rendering the key when entering the page again.
        return () => {
            page = 0;
            pageIndex = 0;
            sectionIDs = [];
            rowIDs = [];
    }, [])


Keywords: Front-end antd

Added by robinjohn on Fri, 04 Mar 2022 23:52:15 +0200