【问题标题】:Fetch not responding获取没有响应
【发布时间】:2022-01-18 16:48:30
【问题描述】:

我有这个 App 组件,我想从背面的 API 中获取一些数据:

const App = () => {
  const [restaurants, setRestaurants] = useState("");

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          "http://localhost:3001/api/v1/restaurants"
        );
        const data = await response.json();
        console.log(data);
        setRestaurants(data);
      } catch (err) {
        console.log("Cant fetch");
      }
    };
    fetchData();
  }, []);

  return (
    // <RestaurantContextProvider>
    <div className="container">
      <Router>
        <Routes>
          <Route exact path="/" element={<Home restaurants={restaurants} />} />
          <Route
            exact
            path="/restaurants/:id/update"
            element={<UpdatePage />}
          />
          <Route
            exact
            path="/restaurants/:id"
            element={<RestaurantDetailPage />}
          />
        </Routes>
      </Router>
    </div>
    // </RestaurantContextProvider>
  );
};

export default App;

如果我在 Route 元素中更改组件的元素,它会获取但不会呈现。 怎么了?我在Router的V6文档上没有找到答案。

已编辑:

如果我在这个组件中添加 fetch,它会正常获取数据。

const RestaurantsList = (restaurants) => {
  

  return (
    <div className="list-group">
      <table className="table table-hover table-dark">
        
        <tbody>
          {restaurants &&
            restaurants.map((res) => (
              <tr key={res.id}>
                <td>{res.name}</td>
                <td>{res.location}</td>
                <td>{"$".repeat(res.price_range)}</td>
                <td>Reviews</td>
                <td>
                  <button className="btn btn-warning">Update</button>
                </td>
                <td>
                  <button className="btn btn-danger">Delete</button>
                </td>
              </tr>
            ))}
        </tbody>
      </table>
    </div>
  );
};

export default RestaurantsList;

这里是 index.js:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

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

【问题讨论】:

  • 我的意思是......如果出现错误,您没有更新饱和状态,因此获取可能存在错误?
  • 我不明白。如果我在孩子中获取数据,它可以正常工作
  • 你试过 route 的 render props 吗? &lt;Route render={(routerProps =&gt; &lt;Home restaurants={restaurants} {...routerProps} /&gt;
  • 您需要在 useEffect 挂钩中将餐厅作为依赖项传递。基于依赖关系,重新渲染发生。在 useState 中也使用空数组而不是空字符串。
  • @miouri 你的 fetchData 应该返回一个承诺。您编写方法的方式没有遵循最佳实践。您可以在 useEffect 之外声明 fetchData,并将方法名称作为依赖项传递给 useEffect。您也可以使用 useCallback 为记忆版本包装 fetchData。现在你试试这样 useEffect(() => { fetchData().then((data) => setRestaurants(data)); }, []);

标签: reactjs react-router


【解决方案1】:

您可能已经在App 中的挂载useEffect 钩子中成功调用了fetchData,并在restaurants 道具上将restaurants 状态传递给Home

<Route path="/" element={<Home restaurants={restaurants} />} />

但是在路由组件中,您根本没有访问 restaurants 道具,而是将道具对象命名为 restaurants 并尝试映射它。 React props 对象,如果分配给一个参数,则总是定义,但它是一个对象,而不是一个数组。

const RestaurantsList = (restaurants) => { // <-- props object is restaurants
  return (
    <div className="list-group">
      <table className="table table-hover table-dark">
        <tbody>
          {restaurants &&
            restaurants.map((res) => (
              <tr key={res.id}>
                <td>{res.name}</td>
                <td>{res.location}</td>
                <td>{"$".repeat(res.price_range)}</td>
                <td>Reviews</td>
                <td>
                  <button className="btn btn-warning">Update</button>
                </td>
                <td>
                  <button className="btn btn-danger">Delete</button>
                </td>
              </tr>
            ))}
        </tbody>
      </table>
    </div>
  );
};

解决:

  1. 访问 restaurants.restaurants 以获取 实际 restaurants 属性,该属性是要映射的数组。

    const RestaurantsList = (restaurants) => {
      return (
        <div className="list-group">
          <table className="table table-hover table-dark">
            <tbody>
              {restaurants.restaurants.map((res) => (
                <tr key={res.id}>
                  ...
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    };
    

    不过,按照惯例,您应该将 props 对象命名为 props,以便更清楚它是什么,并且不会导致您的困惑。

    const RestaurantsList = (props) => {
      return (
        <div className="list-group">
          <table className="table table-hover table-dark">
            <tbody>
              {props.restaurants.map((res) => (
                <tr key={res.id}>
                  ...
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    };
    
  2. 使用道具destructuring assignment 到达restaurants 道具。

    const RestaurantsList = (props) => {
      const { restaurants } = props;
      return (
        <div className="list-group">
          <table className="table table-hover table-dark">
            <tbody>
              {restaurants.map((res) => (
                <tr key={res.id}>
                  ...
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    };
    

    const RestaurantsList = ({ restaurants }) => {
      return (
        <div className="list-group">
          <table className="table table-hover table-dark">
            <tbody>
              {restaurants.map((res) => (
                <tr key={res.id}>
                  ...
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    };
    

App 组件中,请确保您保持数组状态不变,因此children 中的restaurants 属性始终是有效数组,并且可以通过使用空数组[] 作为空字符串@987654344 上的初始状态进行映射@。

const [restaurants, setRestaurants] = useState([]);

【讨论】:

  • 由于某种原因无法使用您的解决方案....
  • @miouri 您在App 的哪个位置登录调试?请求是否发出,您是否在浏览器开发工具的网络选项卡中看到它?如果是这样,在useEffectfetchData函数中记录的console.log(data);的值是多少?
  • i´m console.log 在 fetch 函数内部和设置状态后:useEffect(() => { const fetchData = async () => { try { const response = await fetch( "@ 987654322@" ); const data = await response.json(); setRestaurants(data); console.log(restaurants); } catch (err) { console.log("Cant fetch"); } }; fetchData(); }, [餐厅]);
  • 也许是路由器的问题?我正在使用V6。我用 index.js 更新了代码,请看一下。
  • @miouri React 状态更新是异步处理的,您无法在更新入队后记录restaurants 状态right,因为它将记录当前渲染的状态值周期,而不是更新后的后续渲染周期。使用useEffect(() =&gt; console.log(restaurants), [restaurants]); 记录状态更新。
猜你喜欢
  • 2023-01-12
  • 1970-01-01
  • 2016-05-13
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2012-04-01
相关资源
最近更新 更多