简体   繁体   English

在 React.js 中刷新时丢失 useState 值

[英]Losing useState Value on Refresh in React.js

I am sending an id from ProductListing Component and I am receiving that id using useParams in ProductDetail Component.我正在从ProductListing组件发送一个id ,并且我正在使用ProductDetail组件中的useParams接收该id In ProductDetail Component I am finding an object using find method and then I am setting it into singleProduct state.ProductDetail组件中,我使用 find 方法找到了 object,然后将其设置为singleProduct state。 On refresh I get singleProduct is undefined.刷新时我得到singleProduct未定义。

imports进口

import React, { useState, useEffect } from "react";
import { NavLink, useParams } from "react-router-dom";
import Loading from "../other/Loading";

state state

const ProductDetail = () => {
  const [loading, setLoading] = useState(false);
  const [products, setProducts] = useState([]);
  const [singleProduct, setSingleProduct] = useState({});

receiving an id using useParams使用 useParams 接收 id

  const { id } = useParams();

useEffect使用效果

  useEffect(() => {
   //GETTING PRODUCTS ARRAY
    getProductListingData();
   //FINDING A SINGLE OBJECT
    getProductID();
  }, []);

getting products array获取产品数组

const getProductListingData = async () => {
    try {
      const response = await fetch("http://localhost:8000/productListing");
      const data = await response.json();
      if (data) {
        setLoading(false);
        setProducts(data.products);
      } else {
        setProducts("PRODUCT LISTING DATA NOT FOUND");
      }
    } catch (error) {
      console.log(error);
    }
  };

  if (loading) {
    return <Loading loadingProductListing="Loading Product List" />;
  }

  const getProductID = () => {
    let foundProduct = {};
    foundProduct = products.find((item) => {
      return item.id === parseInt(id);
    });
    setSingleProduct(foundProduct);
  };

  // console.log("product ID = ", productID, typeof productID);
  console.log("products = ", products);
  console.log("singleproduct = ", singleProduct);

JSX JSX

return (
    <>
      <div className="dvProducts col-12">
              <div className="row">
                <div className="col-12">
                  <NavLink
                    to="/product-listing"
                    className="text-dark mb-1 d-inline-block"
                  >
                    <i className="fa fa-angle-left f16"></i>
                    <span> Back</span>
                  </NavLink>
                </div>
                <div className="col-12 col-md-6 col-xl-4 mb-3">
                  <div className="border border-light shadow-sm p-1 h-100">
                    <div className="bg-light text-center p-5">
                      <a className="d-inline-block">
                        <img
                          src="images/description/coconut-water-200ml.png"
                          className="img-fluid"
                          alt="..."
                        />
                      </a>
                    </div>
                  </div>
                </div>
                <div className="col-12 col-md-6 col-xl-8 d-flex mb-3 mb-xl-0">
                  <div className="m-md-auto">
                    <div>
                      <h4>Coconut Water</h4>
                    </div>
                    <div className="mb-2">
                      <i className="fa fa-star text-warning d-inline-block"></i>
                      <i className="fa fa-star text-warning d-inline-block"></i>
                      <i className="fa fa-star text-warning d-inline-block"></i>
                      <i className="fa fa-star-o text-warning d-inline-block"></i>
                      <i className="fa fa-star-o text-warning d-inline-block"></i>
                    </div>
                    <div className="mb-3">
                      <p>
                        Every athlete's go to natural energy drink; Coconut
                        Water is a complete win-win for your everyday
                        rehydration needs. #iaminlovewiththecoco!
                      </p>
                    </div>
                    <div className="d-flex mb-3">
                      <div className="mr-2">
                        <h6 className="d-inline-block mb-1">Size:</h6>
                        <span className="d-inline-block">200ml</span>
                      </div>
                      <div className="mr-2 ml-2">
                        <h6 className="d-inline-block mb-1">Category:</h6>
                        <span className="d-inline-block">Juices</span>
                      </div>
                      <div className="ml-2">
                        <h6 className="d-inline-block mb-1">Price:</h6>
                        <span className="d-inline-block">
                          <i className="fa fa-inr"></i>
                          <span className="d-inline-block">40.00</span>
                        </span>
                      </div>
                    </div>
                    <div>
                      <button
                        className="btn btnSecondary"
                        href="detail.html"
                      >
                        Add to Bag
                      </button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
    </>
  );
};

export default ProductDetail;

That's a normal behaviour, state is being reset on refresh per specification.这是正常行为,state 正在按照规范在刷新时重置。 If you want to preserve it you need to make use of localStorage/sessionStorage/cookies etc.如果你想保存它,你需要使用 localStorage/sessionStorage/cookies 等。

Which is best way?哪个是最好的方法?

Well I would say that the second approach is better.好吧,我会说第二种方法更好。 I would avoid keeping copy of state in localstorage.我会避免在本地存储中保留 state 的副本。 I would only keep some kind of token/id (in your case uid) which uniquely identify the user and would fetch fresh data every time.我只会保留某种令牌/ID(在您的情况下为 uid),它唯一地标识用户并且每次都会获取新数据。 When your application grows it can be hard to manage those states in localstorage.当您的应用程序增长时,可能很难在本地存储中管理这些状态。

const getProductListingData = async () => {
try {
  const response = await fetch("http://localhost:8000/productListing");
  const data = await response.json();
  if (data) {
    setLoading(false);
    setProducts(data.products);
       // call this function after you are getting list of products
   getProductID(data.products);
   } else {
    setProducts("PRODUCT LISTING DATA NOT FOUND");
        
    }
 } catch (error) {
  console.log(error);
 }
 };

const getProductID = (tempProducts) => {
let foundProduct = {};
foundProduct = tempProducts.find((item) => {
  return item.id === parseInt(id);
});
setSingleProduct(foundProduct);
};

You can't persist the data on page refresh with useState hook, better way is to pass that id as url params and check if there is any id in url then fetch the product.您不能使用 useState 挂钩在页面刷新时保留数据,更好的方法是将该 id 作为 url 参数传递,并检查 url 中是否有任何 id 然后获取产品。 your single page route should accept a param like.您的单页路由应该接受类似的参数。

"/route/:id"

You can check this code snippet.您可以检查此代码段。 How to set and get route params in react 如何在反应中设置和获取路由参数

use localstorage使用本地存储

npm install reactjs-localstorage npm 安装 reactjs-localstorage

in your project:在您的项目中:

import {reactLocalStorage} from 'reactjs-localstorage';

set and get your value everywhere you want在任何你想要的地方设置并获得你的价值

reactLocalStorage.set('var', true);
reactLocalStorage.get('var', true);
reactLocalStorage.setObject('var', {'test': 'test'});
reactLocalStorage.getObject('var');
reactLocalStorage.remove('var');
reactLocalStorage.clear();

source: https://www.npmjs.com/package/reactjs-localstorage来源: https://www.npmjs.com/package/reactjs-localstorage

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM