我使用的是React 18.2.0,其中我有一个BodyComponent,它将results从API调用存储到状态,并将filters存储在调用中.

BodyComponent在加载时用挂钩从会话存储器中检索resultsfilters,并在results被更新时更新sessionStorage.

export default function BodyComponent(){

    const [results, setResults] = useState([]);
    const [filters, setFilters] = useState([]);
    
    useEffect(() => {
        if (window.sessionStorage.getItem('results') !== null) {
            setResults(JSON.parse(window.sessionStorage.getItem('results')));
        }
        if (window.sessionStorage.getItem('filters') !== null && filters.length === 0) {
            setFilters(JSON.parse(window.sessionStorage.getItem('filters')));
        }
    }, []);


    useEffect(() => {
        window.sessionStorage.setItem('results', JSON.stringify(results));
    }, [results]);

    return (
    ...
    <FilterComponent filters={filters} setFilters={setFilters}/>
    ...
    )

}

筛选器组件将筛选器更新到会话存储:

export default function FilterComponent(props) {
    const {filters, setFilters} = props; 

    useEffect(() => {
        window.sessionStorage.setItem('filters', JSON.stringify(filters));
    }, [filters]);

    return (
    ...
    )
}

当我导航到另一个react 路由并返回到加载BodyComponent的路由时,filters被保存到会话存储中,BodyComponent成功地检索它们并在加载时将它们传递给FilterComponent.

然而,results并非如此,它们保存到会话存储中,但不会设置为加载时的状态.

我try 了以下几种方法:

  • 在BodyComponent的父组件上处理状态和会话存储,认为这将是一个异步状态更新的问题. 当我这样做时,不仅没有解决问题,而且过滤器也不再正确加载.

  • 无论我在哪里更新会话存储,都要手动更新它(这是很糟糕的做法,但我已经try 过了),我认为这会是一个问题,因为挂钩没有正确地检测到更新. 这并没有改变任何事情.

  • 将写入会话存储的useEffect复制到涉及的每个组件中. 这也没有改变任何事情.

我遗漏了什么?

推荐答案

const [results, setResults] = useState([]);

useEffect(() => {
  console.log(results); // results is empty on the first render 
  window.sessionStorage.setItem('results', JSON.stringify(results));
}, [results]);

第一次执行效果时,results为空,因此您可以在初始渲染后重置结果.

documentation开始,useState可以使用initializer function来计算初始状态(此函数仅在组件初始化时调用一次).

function load(key) {
  const item = window.sessionStorage.getItem(key);
  return item != null ? JSON.parse(item) : [];
}

export default function BodyComponent(){
    const [results, setResults] = useState(() => load('results'));
    const [filters, setFilters] = useState(() => load('filters'));

    useEffect(() => {
        window.sessionStorage.setItem('results', JSON.stringify(results));
    }, [results]);
    
    ....
}

Javascript相关问答推荐

获取最接近的父项(即自定义元素)

React状态变量在使用++前置更新时引发错误

如何避免使用ajax在Vue 3合成API中重定向

为什么我达到了时间限制!?LeetCode链接列表循环(已解决,但需要解释!)

主要内部的ExtJS多个子应用程序

React:未调用useState变量在调试器的事件处理程序中不可用

IMDB使用 puppeteer 加载更多按钮(nodejs)

类型脚本中只有字符串或数字键而不是符号键的对象

如何通过将实例方法的名称传递给具有正确类型的参数的继承方法来调用实例方法?

您能在卸载程序(QtInsteller框架)上添加WizardPage吗?

TypeError:无法分解';React2.useContext(...)';的属性';basename';,因为它为空

环境值在.js文件/Next.js中不起作用

当用户点击保存按钮时,如何实现任务的更改?

从另一个数组中的对应行/键值对更新数组中的键值对对象

为什么可选参数的顺序会导致问题?

当标题被点击时,如何使内容出现在另一个div上?

为什么NULL不能在构造函数的.Prototype中工作

为什么我不能使用其同级元素调用和更新子元素?

输入数据覆盖JSON文件

在点击链接后重定向至url之前暂停