出现在 useEffect 状态更新后 React 没有重新渲染(Reask)

时间:2021-02-08 20:02:42

标签: javascript reactjs jsx

总结问题

目标

我正在尝试为我的 Shop Inventory 项目创建购物车功能。这个购物车基本上将包含一个产品 ID 列表,并最终允许用户查看这个“购物车”中的所有项目。一旦用户觉得他们已将所有想要购买的产品添加到购物车中,他们就会在购物车页面中显示一个按钮来购买购物车中的所有产品。

理想情况下,我将在本地存储中存储产品 id 列表,一旦用户导航到某个路线,我将使用 JSON.parse/JSON.stringify 从本地存储中获取列表并相应地实现该功能(Putting产品 ID 转换为称为产品的状态变量)。除了我放置的一些调试代码外,它似乎工作正常。

预期与实际

我已将此调试代码放入我的组件中,以显示从本地存储中获取的产品列表。

{products.map((product) => {
    <h2>{product}</h2>;
  })
}

然而,每当我加载页面时,我看到的唯一内容是更多的调试内容,比如我放在它上面的“Hello World”。当我加载页面时,我希望看到的是与放入购物车的产品对应的 ID 列表。通过查看反应开发工具,我知道它在“产品”状态变量中至少有一个产品。

错误信息

没有错误消息。

描述您尝试过的内容

调试尝试

React 开发工具

我能够确认即使状态变量列表未显示,状态变量本身也在更新。我能够使用 React Dev Tools 验证这一点。

VS 调试器

我还尝试在设置状态之前和之后查看调试器。我设置的数组似乎是正确的:

我注意到在经历了相当多的 React 内部工作之后,它又回到了我在 useEffect 中的代码。当它发生时,产品状态变量被正确更新。然而,在我使用调试器执行的接下来的几个步骤中,它似乎并没有回到我的视觉部分重新渲染它。

堆栈溢出

我搜索了一些在问这个问题时出现的 Stack Overflow 问题。我相信最接近的问题是尚未回答的 one。其中一些在使用子组件和直接访问状态变量而不是使用 set 时遇到了麻烦,我没有这样做。对于子问题,我看的主要问题是这个one。对于直接访问这是主要的 one

显示一些代码

Cart.js

使用功能性反应组件,我有一个“产品”状态变量,我尝试使用本地存储中的某个键填充 useEffect 钩子。下面是我的购物车组件。您可能会注意到还有另一个名为“addingResource”的状态变量,用于指示是否已创建 Cart 组件以将资源添加到购物车或只是显示它。正如您所看到的,addingResource 状态变量也在 useEffect 钩子中更新。我不完全确定这是否可能是影响产品状态变量的原因,但我想我会在此处注明,以防万一。再一次的主要问题是 return 语句中的产品映射函数没有显示任何项目,即使产品状态变量似乎已更新。

function Cart(props) {
    const [products, setProducts] = React.useState([]);
    const [addingResource, setAddingResource] = React.useState(false);

    const REACT_APP_CART_TOKEN_NAME = process.env.REACT_APP_CART_TOKEN_NAME;

    // Ensures that addingResource is updated to true if needed
    React.useEffect(() => {
        if (props.match && addingResource === false) {
            setAddingResource(true);
        }

        const stringVersion = window.localStorage.getItem(
            REACT_APP_CART_TOKEN_NAME
        );

        let productIdsList = [];

        if (stringVersion) {
            productIdsList = JSON.parse(stringVersion);
            console.log("test");
        }

        if (props.match) {
            productIdsList.push(props.match.params.id);
            window.localStorage.setItem(
                REACT_APP_CART_TOKEN_NAME,
                JSON.stringify(productIdsList)
            );
        }

        alert("Updating Products");
        if (!products) {
            setProducts(productIdsList);
        }
    }, []);

    // TODO: Read the products key from the local storage
    return (
        <>
            <h1>Match: {`${addingResource}`}</h1>
            {products &&
                products.map((product) => {
                    <h2>{product}</h2>;
                })}
        </>
    );
}

本地存储“购物车”令牌

此外,此组件中正在访问的“cart”本地存储令牌具有以下结构:

[
    '5fccb14ed0822f25ec5cee63'
]

结束语

这是从我最初关闭的问题中重新创建的问题,您可以找到 here。我相信它被关闭的原因是我在提交问题时遇到了问题。似乎有一段代码被堆栈溢出说是无效的。我已经查看了我放入的所有代码段,但似乎没有一个是错误的。我什至尝试在文本编辑器中格式化间距并将其粘贴几次以确保其间距正确。我什至删除了所有代码片段并尝试以这种方式提交。但是,它仍然告诉我我的帖子中某处有错误。然后,我尝试通过慢慢删除帖子的某些部分并尝试提交来使用消除过程来解决此问题。这导致的问题是我最初的帖子只有原始帖子的一小部分。我试图快速找到错误并填写其余信息。我最终能够找到导致此错误的“React Dev Tools”段落附近的文本部分。解决此错误后,我能够以完整的形式提交我的帖子。不幸的是,我的问题似乎已经关闭,即使在我原来的冗长帖子中添加了一些额外的细节并放置了一个部分之后,要求关闭问题的人再次查看它并在有任何问题时给我发消息,它几乎保持关闭状态一周。因此,我决定发布一个新帖子,以确保我的原始帖子的所有内容都可以从第一个版本中获得。

我非常感谢任何帮助,并希望为我和将来遇到此问题的人解决此问题。谢谢!

1 个答案:

答案 0 :(得分:1)

你的 useEffect 看起来不错。但是您需要在 map 函数中返回一个值,否则它不会显示任何内容:

k

当您移除箭头函数内容周围的大括号时,它被视为返回值。否则,您可以简单地写 return ( <> {products.map(product => <h2>{product}</h2>)} </> );