You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中Session Storage存储滑块偏好值返回首页被重置的问题求助

问题分析

问题出在组件初始化阶段:

  • 你给useState设置的初始值是null,导致组件挂载时,依赖value的useEffect会立即把sessionStorage中的值覆盖为null。
  • 随后执行的空依赖useEffect读取的已经是被覆盖后的null,最终把state设为null,形成恶性循环。

另外你的Slider组件里有个冗余的handleChange函数,既没有用到,还会因为内部没有setValue导致报错,需要删掉。

修复方案

1. 初始化state时直接读取sessionStorage

不需要用额外的useEffect初始化state,直接在useState的初始化函数中读取sessionStorage,这样初始值就会是用户之前存储的偏好值,避免挂载时写入null。

2. 移除冗余代码

删掉Slider组件内多余的handleChange函数,同时移除ImageGallery中用于初始化state的空依赖useEffect。

修改后的代码

Slider组件

export default function Slider({ value, handleChange }: ISlider) {
  return (
    <input
      className={styles.slider}
      min={1}
      max={3}
      step={1}
      type="range"
      value={value}
      onInput={handleChange}
      onChange={handleChange}
    />
  );
}

ImageGallery组件

export default function ImageGallery({
  projects,
}: {
  projects: any;
}): JSX.Element {
  // 初始化时直接从sessionStorage取值,默认值设为1
  const [value, setValue] = useState(() => {
    if (typeof window !== "undefined") {
      const storedValue = window.sessionStorage.getItem("value");
      return storedValue ? JSON.parse(storedValue) : 1;
    }
    return 1;
  });

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(Number(event.target.value)); // 转为number类型,避免字符串问题
  };

  // 仅在value变化时存储到sessionStorage
  useEffect(() => {
    if (typeof window !== "undefined") {
      window.sessionStorage.setItem("value", JSON.stringify(value));
    }
  }, [value]);

  const breakpointColumnsObj = {
    default: 4,
    1100: 3,
    700: 2,
    500: value
  };

  return (
    <>
      <Masonry
        breakpointCols={breakpointColumnsObj}
        className={styles.myMasonryGrid}
        columnClassName={styles.myMasonryGridColumn}
      >
        {projects.map((item: any) => {
          const images = item.images.data.attributes.formats.large;
          return (
            <ImageCard
              key={item.slug}
              src={images.url}
              alt={item.images.data.attributes.caption}
              width={images.width}
              height={images.height}
              slug={item.slug}
              id={item.slug}
            />
          );
        })}
      </Masonry>
      <Slider value={value} handleChange={handleChange} />
    </>
  );
}

额外优化建议

  • 给ISlider接口添加明确的类型定义:
    interface ISlider {
      value: number;
      handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
    }
    
  • 给projects参数定义具体的类型,避免使用any,提升代码可维护性。

内容的提问来源于stack exchange,提问作者Antoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:20:47