首页 > 解决方案 > 使用本地存储在 gatsby 构建中未更新图像源

问题描述

我正在尝试为第一次使用 gatsby 访问网站的用户显示不同的图像集localstorage,一切都在 gatsby develop 中按预期工作,但是当我使用 gatsby build 构建网站以进行生产使用时,它总是返回意味着显示的图像仅限初次使用的用户。这是完整的代码

import * as React from 'react';
import { Component } from 'react';

let visited = typeof window !== 'undefined' && window.localStorage.getItem('visited')
var items = [
  "https://picsum.photos/id/40/200/300", 
  "https://picsum.photos/id/30/200/300",
  "https://picsum.photos/id/20/200/300",
  "https://picsum.photos/id/10/200/300"
]

class IndexPage extends Component {

  reTargetImages() {
        typeof window !== 'undefined' && window.localStorage.setItem("visited", JSON.stringify('1'));
    }

  componentDidMount() {
    this.reTargetImages()
  }

  render() {
    if(!visited) {
      items = [
        "https://picsum.photos/id/10/200/300", 
        "https://picsum.photos/id/30/200/300",
        "https://picsum.photos/id/20/200/300",
        "https://picsum.photos/id/40/200/300"
      ]
    }
    return (
      <main>
        <title>Home Page</title>
        <h1>
          Congratulations
          <br />
          <span>— you just made a Gatsby site! </span>
          {items && items.map((item, index) => {
            return (
              <img id={`img-${index}`} src={`${item}`} />
            )
          })}
          </span>
        </h1>
      </main>
  )
  }
}

export default IndexPage

localstorage即使设置正确,代码也始终返回适用于首次使用的用户的图像。IE

      [
        "https://picsum.photos/id/10/200/300", 
        "https://picsum.photos/id/30/200/300",
        "https://picsum.photos/id/20/200/300",
        "https://picsum.photos/id/40/200/300"
      ]

该问题仅在生产构建中出现,并且在开发中运行良好

标签: javascriptreactjslocal-storagegatsby

解决方案


您应该需要使用状态来强制更改items变量。静态方法在这里不适合(或者可能会导致您出现一些不需要的行为)。此外,使用布尔值使您的条件不成立。就像是:

import * as React from 'react';
import { Component } from 'react';

let visited = typeof window !== 'undefined' && window.localStorage.getItem('visited')

class IndexPage extends Component {
   constructor() {
    super();
    this.state = {items: [      
      "https://picsum.photos/id/40/200/300", 
      "https://picsum.photos/id/30/200/300",
      "https://picsum.photos/id/20/200/300",
      "https://picsum.photos/id/10/200/300"
    ]};
   }
  
  reTargetImages() {
        typeof window !== 'undefined' && window.localStorage.setItem("visited", true));
    }

  componentDidMount() {
    this.reTargetImages()
  }

  render() {
    if(!visited) {
      this.setState({
         items: [
            "https://picsum.photos/id/10/200/300", 
           "https://picsum.photos/id/30/200/300",
           "https://picsum.photos/id/20/200/300",
           "https://picsum.photos/id/40/200/300"
         ]
      })
    }
    return (
      <main>
        <title>Home Page</title>
        <h1>
          Congratulations
          <br />
          <span>— you just made a Gatsby site! </span>
          {this.state.items && this.state.items.map((item, index) => {
            return (
              <img key={`img-${index}`} id={`img-${index}`} src={item} />
            )
          })}
          </span>
        </h1>
      </main>
  )
  }
}

export default IndexPage

此外,key在使用渲染元素的循环时添加该属性。

请记住,您正在将 DOM 树加载为true(或1在您的情况下)中的visited变量,componentDidMount因此一旦加载 DOM 树,它将匹配!visited显示原始items. 我不认为这是否是您想要实现的,但这是使用状态更改相同变量以使用相同代码显示不同结果的正确方法。

我还建议您visited在您的状态中添加变量,localStorage并在需要时相应地更改两者。


推荐阅读