如何在 React 中保存路由更改之间的状态

cas*_*per 4 caching reactjs

我有一个简单的应用程序,显示当地酒店的列表。每个列表项都有一个<Link/>重定向到另一个组件的组件,该组件在地图上显示该特定酒店的位置。当切换路由时,组件似乎<ProductList/>被破坏了,其中的所有状态也被破坏了。所以每次当它进行新的 API 调用并重新渲染时。我尝试将其保存在本地存储中componentWillUnmount并检索它,useEffect()以便我可以有条件地进行 API 调用,它可以工作,但有时不起作用。

import React, { useState, useEffect} from "react";
import ProductItem from "../Components/ProductItem";
import axios from "axios";

const ProductList = () => {
  const [hotelList, setHotelList] = useState([]);

  // Get user location by IP
  const getCurrentLocation = () => {
    return fetch("https://ipinfo.io/json?token=MyToken").then(
      (response) => response.json()
    );
  };

  // Get list of hotels in specific location
  const getHotelsInLocation = (destInfo) => {
    console.log('destInfo is: ', destInfo)
    const options = {
      method: "GET",
      url: "https://booking-com.p.rapidapi.com/v1/hotels/search",
      params: {
        checkout_date: "2022-10-01",
        units: "metric",
        dest_id: destInfo.destId,
        dest_type: destInfo.destType,
        locale: "en-gb",
        adults_number: 2,
        order_by: "popularity",
        filter_by_currency: "USD",
        checkin_date: "2022-09-30",
        room_number: 1,
      },
      headers: {
        "X-RapidAPI-Host": "booking-com.p.rapidapi.com",
        "X-RapidAPI-Key": "MyApiKey",
      },
    };
    axios
      .request(options)
      .then(function (response) {
        console.log(response.data.result);
        setHotelList(response.data.result);
      })
      .catch(function (error) {
        console.error(error);
      });
  };

  useEffect(() => {
    getCurrentLocation().then((currentLocation) => {
      console.log("Current city ", currentLocation.city);
      const options = {
        method: "GET",
        url: "https://booking-com.p.rapidapi.com/v1/hotels/locations",
        params: { locale: "en-gb", name: currentLocation.city },
        headers: {
          "X-RapidAPI-Host": "booking-com.p.rapidapi.com",
          "X-RapidAPI-Key":
            "MyApiKey",
        },
      };
      axios
        .request(options)
        .then(function (response) {
          console.log(response.data);
          let destId = response.data[0].dest_id;
          let destType = response.data[0].dest_type;
          const destInfo = { destId, destType };
          getHotelsInLocation(destInfo);
        })
        .catch(function (error) {
          console.error(error);
        });
    });
  }, []);

  return (
    <>
      {hotelList.map((hotel) => (
        <ProductItem key={hotel.hotel_id} hotel={hotel} />
      ))}
    </>
  );
};

export default ProductList;
Run Code Online (Sandbox Code Playgroud)

当我回到<ProductList/>组件时,我怎么能这样做,它不会发出新的 API 调用,而只是显示hotelList上一次调用的 API 调用。

Suj*_*eep 5

在这种情况下,您需要将数据保存在集中存储中。为此,您有两个选择。一种是使用 context api,这是默认的 React 功能。另一种是使用 redux,它是单独的包。

我的意见是,你可以使用 context api。

下面给出了 context api 的一个简单示例,

文件上下文.jsx

import { createContext } from 'react'

export const Filecontext = createContext({});
Run Code Online (Sandbox Code Playgroud)

表单组件.jsx

import { Filecontext } from '../Contexts/Filecontext';
import { useContext } from 'react'

export default function Formcomponent() {
    const { setName, setEmail, setMobileno, showAlert } = useContext(Filecontext)

    return (
        <>
            <div className="form-group">
                <label>Name : </label>
                <input type="text" onChange={(e) => { setName(e.target.value) }} />
            </div>
            <div className="form-group">
                <label>Email : </label>
                <input type="email" onChange={(e) => { setEmail(e.target.value) }} />
            </div>
            <div className="form-group">
                <label>Mobile No : </label>
                <input type="number" onChange={(e) => { setMobileno(e.target.value) }} />
            </div>
            <div className="form-group">
                <input type="submit" value="submit" onClick={() => { showAlert() }} />
            </div>
        </>
    )
}
Run Code Online (Sandbox Code Playgroud)

列表组件.jsx

import { Filecontext } from '../Contexts/Filecontext';
import { useContext } from 'react'

export default function Listcomponent() {
    const { name, email, mobileno } = useContext(Filecontext)
    return (
        <>
            <p>Name :</p>{name}
            <p>Email :</p>{email}
            <p>Mobile No :</p>{mobileno}
        </>
    )
}
Run Code Online (Sandbox Code Playgroud)

应用程序.js

import logo from './logo.svg';
import './App.css';
import Formcomponent from './Components/Formcomponent';
import Listcomponent from './Components/Listcomponent';

import { Filecontext } from './Contexts/Filecontext';
import { useState } from 'react'

function App() {
  const [name, setName] = useState("")
  const [email, setEmail] = useState("")
  const [mobileno, setMobileno] = useState("")

  return (
    <div className="App">
      <Filecontext.Provider value={{ name, setName, email, setEmail, mobileno, setMobileno, showAlert }}>
        <Formcomponent />
        <Listcomponent />
      </Filecontext.Provider>

    </div>
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

从上面的例子可以看出,Formcomponent可以在不同的路由中显示,也Listcomponent可以在不同的路由中显示。但即便如此,数据也可以在上下文的帮助下保留。