侧边栏及查看更多按钮

103 阅读5分钟

侧边栏的请求

期望结果:

输入值之后 点击apply可以完整地将输入值拼贴到请求路径中

image-20231113135233727.png

问题:

拼贴到请求路径的值总是比实际输入的值少一位(慢一位)

背景:

真正发送网络不是在这个组件,而是在外层filter页面,用了dispatch将输入值minValue和maxValue传递给外层filter页面,filter页面useEffect监听,变化了就去发送请求

解决过程:

是dispatch出了问题吗?使用到的数据总是少一位 可能是没有及时dispatch,看handleMinMaxInput是怎么将值存储起来的,结果确实是这个函数的问题

    const handleMinMaxInput = (value: number, valueType: string) => {
        console.log("value", value)
        // 这里clg还是对的
        console.log("valueType", valueType)
        if (valueType == 'min') {
            dispatch(setVolumeMin({ volume_min: value }));
            setMinValue(value);
            setIsMin(true)
        } else if (valueType == 'max') {
            console.log("1015", valueType, value)//这里也是对的
            dispatch(setVolumeMax({ volume_max: value }))//在这里就去dispatch 因为后面set会异步 然后再去取值diapatch会慢一步
            setMaxValue(value);
            setIsMax(true)
        }
        // 从这里开始就慢了
        console.log("volume_max", maxValue)
        // 不要在这里再去dispatch
        // valueType == 'max' && dispatch(setVolumeMax({ volume_max: maxValue }));
    }

这个功能模块在其他地方也有用到 当时卡很久,一直没有拿到实时正确的输入值给到请求路径,就先做其他模块,其他模块也用到这个功能,遇到了一样的问题, 逃不掉😶

而且用户如果只是输入min没有输入max这样子max是undefined,发送请求拼贴了undefined会没有结果,所以不能将undefined,NaN的值拼贴进去:

  !isNaN(volume_min) &&
        volume_min &&
        params.push("volume_min=" + volume_min);

在真正发送请求的时候也有问题:

数据没有及时更新到请求中,我在filter页面已经能实时拿到正确的输入值了,但是请求路径有问题,后面发现是 setParamsArray((prevParamsArray) => [...params]); react setState异步导致的

  useEffect(() => {
    console.log("1031end_date_min", end_date_min);//已经能实时拿到正确的输入值了
    console.log("1031end_date_max", end_date_max);
​
    setList([]);
    if (allTabsVisible) {
      console.log("1031endcategory_ids", category_ids?.length !== 0);
      category_ids?.length !== 0 &&
        category_ids &&
        params.push("category_ids=" + category_ids.category_ids.join(","));
      !isNaN(volume_min) &&
        volume_min &&
        params.push("volume_min=" + volume_min);
      !isNaN(volume_max) &&
        volume_max &&
        params.push("volume_max=" + volume_max);
      !isNaN(liquidity_min) &&
        liquidity_min &&
        params.push("liquidity_min=" + liquidity_min);
      !isNaN(liquidity_max) &&
        liquidity_max &&
        params.push("liquidity_max=" + liquidity_max);
      end_date_min !== "" &&
        end_date_min &&
        params.push("end_date_min=" + end_date_min);
      end_date_max !== "" &&
        end_date_max &&
        params.push("end_date_max=" + end_date_max);
      //mark isNaN(null) = false
      is_closed !== undefined &&
        is_closed !== null &&
        params.push("is_closed=" + is_closed);
      featured !== null && params.push("featured=" + featured);
      page !== undefined && params.push("page=" + 1);
      setIsTemplist(true);
​
      search && params.push("group_name=" + encodeURIComponent(search));
      console.log("1031endparams", params);
    } else {
        // 模块的保存值在clear all后也要清除
      dispatch(resetValue());
      dispatch(resetLiquidityValue());
      dispatch(resetStatusValue());
      dispatch(resetEndDateValue());
      dispatch(resetSearchValue());
      dispatch(resetCategoryIdValue());
    }
    setParamsArray((prevParamsArray) => [...params]);
​
    let queryString = `/filter_brief?`;
    // queryString += paramsArray.join('&');
    queryString += params.join("&");//直接用params,而不是paramsArray,因为paramsArray不是实时的
    setQuery(queryString);
​
    if (list.length == 0) {
      getGroups(queryString, false);
    } else {
      setList([]);
      getGroups(queryString, false);
    }
​
  }, [    volume_max,    volume_min,    liquidity_min,    liquidity_max,    end_date_min,    end_date_max,    is_closed,    featured,    search,    category_ids,    allTabsVisible,  ]);

这样就能发送正确的请求了,btn,这还没完 🙉

使用redux store保留了我切换到主页之前点击的筛选项

当我不在filter这个页面,而是切换到主页,再切换到filter页面的时候,数据没有显示,本来是要展示没有拼贴任何筛选项的请求(即/filter_brief? )返回的数据的,结果一条数据都没有,查了网络请求,发现是这样的 /filter_brief?liquidity_min=10000&liquidity_max=50000&page=1 好家伙,使用redux store保留了我切换到主页之前点击的筛选项..

image.png

解决方法:

在每个模块的slice里面再定义一个reset方法将值设置为默认, 在filter页面的useEffect里去调用这些方法,这样首次挂载后就会清除store里面存储的数据了,store里面就都是默认值,请求就只是原来所有数据的了

在每个模块的slice里

// store.ts
import { createSlice } from '@reduxjs/toolkit';
​
// Define the state interface
interface endDateSliceState {
    end_date_min: string | null | undefined;
    end_date_max: string | null | undefined;
}
​
// Define the initial state
const initialState: endDateSliceState = {
    end_date_min: null,
    end_date_max: null,
};
​
// Create a slice with actions and reducer
export const endDateSlice = createSlice({
    name: 'endDateSlice',
    initialState,
    reducers: {
        setEndDateMin: (state: any, { payload }) => {
            state.end_date_min = payload.end_date_min;
        },
        setEndDateMax: (state: any, { payload }) => {
            state.end_date_max = payload.end_date_max;
        },
        //恢复默认值的方法
        resetEndDateValue: (state: any) => {
            state.end_date_min = initialState.end_date_min;
            state.end_date_min = initialState.end_date_max;
        }
    },
});
​
// Export the actions and reducer
export const { setEndDateMin, setEndDateMax, resetEndDateValue } = endDateSlice.actions;
export default endDateSlice.reducer;
 <Link href="/" style={{ textDecoration: "none", color: "#fff" }}>
                <Box
                  className={styles.logoContainer}
                  onClick={resetDataToDefault}//点击logo恢复默认值
                >
                  <Box
                    component="img"
                    width={{ sm: "40px", xs: "40px" }}
                    src="/styles/logo.png"
                  />
                  <Typography fontWeight="700" marginLeft="5px" whiteSpace="nowrap">
                    logo
                  </Typography>
                </Box>
              </Link>
 const resetDataToDefault = () => {
    dispatch(resetValue());
    dispatch(resetLiquidityValue());
    dispatch(resetStatusValue());
    dispatch(resetEndDateValue());
    dispatch(resetSearchValue());
    dispatch(resetCategoryIdValue());
    dispatch(resetFeaturedValue());
  };

在filter:

  useEffect(() => {
      dispatch(resetValue());
      dispatch(resetLiquidityValue());
      dispatch(resetStatusValue());
      dispatch(resetEndDateValue());
      dispatch(resetSearchValue());
      dispatch(resetCategoryIdValue());
  }, [ ]);

点击按钮加载更多

还有数据的加载,这里一开始是去请求第一页的数据,滑倒底部有个查看更多的按钮,点击就要去发送page+1的请求,直到拿到全部数据。这里也是要和其他的参数条件在一起: 首先在每次请求到数据后判断还有没有数据要拿 ,如果有就展示查看更多按钮

 useEffect(() => {
    if (total && list.length >= total) {
      // 请求到的数据还不够 要让page+1之后继续请求
      setHasMore(false);
    }
  }, [list]);
  
  //...
  
    {hasMore ? (
                  <Box display="flex" justifyContent="center">
                 
                    <Button
                      sx={{
                        background: "#22262F",
                        color: "#eee",
                        marginTop: "0.5rem",
                      }}
                      onClick={handleSeeMoreClick}
                    >
                      See More
                    </Button>
                  </Box>
                ) : list.length !== 0 ? (
                  <Box
                    sx={{
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                      flexDirection: "column",
                      marginTop: "50px",
                    }}
                  >
                    <Typography color="rgba(255,255,255,.7)">
                      —— Rock Bottom ——
                    </Typography>
                    <img
                      src="image"
                      alt=""
                      width="80"
                      height="80"
                    />
                    {/* <bottomImg/> */}
                  </Box>
                ) : null}

点击查看更多按钮调用的函数

  const handleSeeMoreClick = () => {
    // 拿到完整的请求参数数组paramsArray后,遍历,查看当前的page是第几页,然后加一,其他的参数原样返回
    let updatedParams = paramsArray.map((param) => {
      if (param?.startsWith("page=")) {
        let currentPage = parseInt(param.split("=")[1]);
        let updatedPage;
        if (list && total) {
          updatedPage = currentPage + 1;
          setPage(updatedPage);
          return "page=" + updatedPage;
        }
      }
      // For other parameters, return them unchanged
      return param;
    });
    setParamsArray(updatedParams);
    let queryString = `/market/filter_brief?` + updatedParams.join("&");
    getGroups(queryString, true);//点击查看更多就让isAddMore为true
  };

最后还有一个点,在点击查看更多的时候,我们是要将请求到的数据添加到原有的数据上,而我们在做条件筛选的时候,是想要在已有的数据中筛出满足条件的数据:

  const getGroups = async (queryString, isAddMore) => {
    //...
  isAddMore ? setList([...list, ...tempList]) : setList([...tempList]);
  }

本来我是将isAddMore作为state的:

  // const [isAddMore, setIsAddMore] = useState(false);

但是这样子在handleSeeMoreClick的时候调用getGroups就不是直接调用,用useEffect去监听isAddMore,变化就调用getGroups,而handleSeeMoreClick要传给getGroups函数queryString,虽然updatedParams存在setParamsArray中,但是这样有异步问题,emm就这个东西也卡了很久,各种set和useEffect太复杂,直接用参数传给getGroups这样来控制isAddMore的值反而更方便,一步到位