【问题标题】:How can I maintain my props/states in ReactJS?如何在 ReactJS 中维护我的道具/状态?
【发布时间】:2020-07-30 04:40:33
【问题描述】:

我目前正在使用以下工作流程构建一个 React 应用程序:

  • 应用程序类别列表,用户将选择一个
  • 一旦用户选择了应用类别,他们就会从列表中选择一种水类型
  • 然后将根据所选的类别和类型显示产品列表。
  • 然后他们可以选择产品来查看信息,例如产品图表、图片等。

问题:

  • 一旦用户选择了一个产品,如果他们点击返回按钮,category 和 type 属性就会丢失。

需要解决方案:

  • 我需要能够始终维护这些道具/状态,以便在用户返回并更改类别/类型时更新它们

我在下面包含了我的代码以供参考。

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>,
  document.getElementById("root")
);

App.js

import React from "react";
import { Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import WaterType from "./components/WaterType";
import Products from "./components/Products";
import Product from "./components/Product";

import "./App.css";

function App() {
  return (
    <div className="App">
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/waterType" component={WaterType} />
        <Route path="/products/:productName" component={Product} />
        <Route path="/products" component={Products} />
      </Switch>
    </div>
  );
}

export default App;

Home.js

import React, { Component } from "react";
import { Link } from "react-router-dom";
import CategoryData from "./data/CategoryData";

class Home extends Component {
  render() {
    return (
      <>
        <h1>Categories</h1>
        <ul>
          {CategoryData.map((cat, i) => (
            <li key={i}>
              <Link
                to={{
                  pathname: "/waterType",
                  name: cat.name,
                }}
              >
                <img src={cat.imageURL} alt={cat.name} />
                {cat.name}
              </Link>
            </li>
          ))}
        </ul>
      </>
    );
  }
}

export default Home;

WaterType.js

import React from "react";
import { Link } from "react-router-dom";
import WaterTypeData from "./data/WaterTypeData";

const WaterType = ({ location }) => {
  const categorySelected = location.name;
  return (
    <>
      <h1>Water Types</h1>
      <p>Current category: {categorySelected}</p>
      <ul>
        {WaterTypeData.map((type, i) => (
          <li key={i}>
            <Link
              to={{
                pathname: "/products",
                categorySelected: categorySelected,
                waterType: type.name,
              }}
            >
              {type.name} - {type.description}
            </Link>
          </li>
        ))}
      </ul>
    </>
  );
};

export default WaterType;

Products.js

import React from "react";
import { Link } from "react-router-dom";
import ProductData from "./data/ProductData";

const Products = ({ location }) => {
  const categorySelected = location.categorySelected;
  const waterType = location.waterType;

  const ProductsResult = ProductData.filter(x => x.categories.includes(categorySelected) && x.waterTypes.includes(waterType));

  return (
    <>
      <h1>Products</h1>
      <p>Current category: {categorySelected && categorySelected}</p>
      <p>Water Type: {waterType && waterType}</p>

      <div className="products">
          <ul>
            {ProductsResult.map((item, i) => (
              <li key={i}>
                <Link
                  to={{
                    pathname: '/products/' + item.slug,
                    name: item.name,
                  }}
                >
                  {item.name}
                </Link>
              </li>
            ))}
          </ul>
      </div>
    </>
  );
};

export default Products;

产品.js

import React from "react";

const Product = ({ location }) => {
  const productName = location.name;

  return (
    <>
      <h1>{productName}</h1>
    </>
  );
};

export default Product;

【问题讨论】:

    标签: javascript reactjs ecmascript-6


    【解决方案1】:

    我强烈推荐 Redux (https://redux.js.org/) 用于应用程序状态管理。 一般来说,将 Redux 包含到现代 React 应用程序中是一个好主意,在您的情况下,它似乎正是您正在寻找的。 希望这可以帮助。 干杯

    【讨论】:

      【解决方案2】:

      我能想到的最简单的解决方案是将您选择的选项(类别和水类型)保留在顶级上下文中。

      类似这样的:

      // ChoicesProvider.js
      import React, { createContext, useState } from "react";
      
      export const ChoicesContext = createContext(null);
      
      export const ChoicesProvider = ({ children }) => {
        const [choices, setChoices] = useState({
          category: null,
          waterType: null,
        });
      
        return (
          <ChoicesContext.Provider value={{ choices, setChoices }}>
            {children}
          </ChoicesContext.Provider>
        );
      };
      

      …然后在你的入口点:

      // index.js
      import React from "react";
      import ReactDOM from "react-dom";
      import App from "./App";
      import { BrowserRouter as Router } from "react-router-dom";
      import { ChoicesProvider } from "./context/ChoicesProvider";
      
      ReactDOM.render(
        <React.StrictMode>
          <ChoicesProvider>
            <Router>
              <App />
            </Router>
          </ChoicesProvider>
        </React.StrictMode>,
        document.getElementById("root")
      );
      
      

      ...然后每次选择类别/水类型时,使用在上下文中定义的 setChoices 将所选状态保存在上下文中。例如:

      // Home.js
      import React, { Component } from "react";
      import { Link } from "react-router-dom";
      import CategoryData from "./data/CategoryData";
      import { ChoicesContext } from "../../context/ChoicesContext";
      
      const Home = () => {
        const { choices, setChoices } = useContext(ChoicesContext);
      
        return (
          <>
            <h1>Categories</h1>
            <ul>
              {CategoryData.map((cat, i) => (
                <li key={i}>
                  <Link
                    onClick={() => setChoices({ ...choices, category: cat.name })}
                    to={{
                      pathname: "/waterType",
                      name: cat.name,
                    }}
                  >
                    <img src={cat.imageURL} alt={cat.name} />
                    {cat.name}
                  </Link>
                </li>
              ))}
            </ul>
          </>
        );
      };
      
      export default Home;
      
      

      希望这能给你一个想法。 祝你有美好的一天?

      【讨论】:

        【解决方案3】:

        首先,我不确定您的路由器设置是否必要。 React 非常适合单页应用程序 (SPA),这意味着,您不需要为每个功能都添加新页面。您可以非常轻松地在单个 Route 上构建您的应用程序,只需更改您当前需要的组件。 所以第一个可能的解决方案是在单页上构建应用程序,使用三个简单的状态

        [category, setCategory] = useState(null)
        [waterType, setWatertype] = useState(null)
        [product, setProduct] = useState(null)
        

        基于此,您可以简单地显示或隐藏选择选项

        <div id="selections">
          {!category && (<Categories />)}
            {(category && !watertype) && (<WaterTypes />)}
            {category && watertype) && (<Products />)}
        </div>
        

        category &amp;&amp; &lt;WaterTypes /&gt; 表示,只有 category 为 true 时才会显示 WaterTypes。

        如果课程要求您将链接替换为类似

        <button type="button" onClick={() => setCategory(cat.name)}>{cat.name}</button>
        

        使用this approach,您可以处理后退和前进按钮来操作您的状态和 URL,这样用户就可以通过像www.youreshop.com?category=first&amp;watertype=second 这样的超链接访问所需的类别

        另一种方法是将context 添加到您的应用中,这样您就可以在各个组件之间共享状态。

        【讨论】:

          猜你喜欢
          • 2019-11-11
          • 2015-08-09
          • 1970-01-01
          • 1970-01-01
          • 2018-11-05
          • 2019-09-06
          • 1970-01-01
          • 2015-12-02
          • 1970-01-01
          相关资源
          最近更新 更多