【问题标题】:Cannot display data with React Router and useParams无法使用 React Router 和 useParams 显示数据
【发布时间】:2021-04-20 10:13:11
【问题描述】:

我正在构建一个 React 应用程序,从以下 API https://jsonplaceholder.typicode.com/users/.The 获取数据我拥有的组件如下:HomePage、UserCard 和 DetailPage。 我想要实现的是: Homepage 组件为每个用户显示一张卡片(因此是 UserCards 组件的列表)。单击 UserCard 时,我被发送到另一个页面(DetailPage),该页面呈现该用户的所有详细信息。 在我的 HomePage 组件中,我使用 Axios 库获取数据,然后映射到数组上,以便显示所有卡片以及一些细节:

const Home = () => {
  const [users, setUsers] = useState([]);
  const getUsers = async () => {
    try {
      const users = await axios.get(
        "https://jsonplaceholder.typicode.com/users"
      );
      setUsers(users.data);

      console.log(users.data);
    } catch (err) {
      console.error(err.message);
    }
  };
  useEffect(() => {
    getUsers();
  }, []);

  return (
    <div className="style">
      <h1 style={{ textAlign: "center", color: "red", marginBottom: "60px" }}>
        Homepage
      </h1>

      <Grid container spacing={7} justify="center">
        {users.map((user) => (
          <Grid key={user.id} item xs={8} sm={5} md={4}>
            {/*curly braces are used for the prop because it's a dynamic value*/}
            <UserCard
              name={user.name}
              username={"@" + user.username}
              website={user.website}
              id={user.id}
            />
          </Grid>
        ))}
      </Grid>
    </div>
  );
};

直到这里一切正常。

我的 UserCard 组件有一个指向 DetailPage 页面的按钮:

<BrowserRouter>
          <div
            className="button-container"
            style={{ width: "100%", display: "flex", justifyContent: "center" }}
          >
            <Button variant="contained" color="primary" disableElevation>
              <Link to={`/ ${props.id}`}>More details</Link>
            </Button>
          </div>
          <Route path="/:id">
            <DetailPage></DetailPage>
          </Route>
        </BrowserRouter>

在 DetailPage 组件中,我再次使用 Axios 获取数据。然后,我使用 useParams 获取所有 URL 参数(在本例中为 :id)并将它们放入一个对象中。然后我想将用户与 id 匹配,以便显示正确的信息。在控制台中,虽然我收到以下错误“TypeError:无法访问属性“名称”,用户未定义”。这是构建应用程序的正确方法吗?我对反应很陌生,我无法理解我的代码有什么问题。

function DetailPage() {
  const [users, setUsers] = useState([]);
  const getUsers = async () => {
    try {
      const users = await axios.get(
        "https://jsonplaceholder.typicode.com/users"
      );
      setUsers(users.data);

      console.log(users.data);
    } catch (err) {
      console.error(err.message);
    }
  };
  useEffect(() => {
    getUsers();
  }, []);
  let { id } = useParams();
  console.log(id);
  let user = findUserById(id);
  function findUserById(id) {
    return users.find((o) => o.id === id);
  }

  return (
    <Container>
      <div>
        <h1>{user.name}</h1>
      </div>
    </Container>
  );
}

【问题讨论】:

    标签: javascript reactjs routes react-router react-hooks


    【解决方案1】:

    当您处理asnyc 数据获取时,您的应用需要处理您的请求仍在重新处理的时间段。

    let user = findUserById(id);
    

    最终user 将解析为一个用户对象,但它在第一次渲染时的值将是undefined,因为users 数组仍然是空的。

    在访问user 对象上的任何属性之前,您需要确保它实际上是一个对象,而不仅仅是undefined,因为访问undefined 上的属性会导致致命错误。

    您可以使用三元运算符或|| / &amp;&amp; 语句。

    return (
        <Container>
        {user ?
          <div>
            <h1>{user.name}</h1>
          </div>
         :
          <div>Loading...<div>
        }
        </Container>
      );
    }
    

    或者有多个returns:

    if ( ! user ) {
      return (
        <div>Loading...</div>
      )
    }
    return (
        <Container>
          <div>
            <h1>{user.name}</h1>
          </div>
        </Container>
      );
    

    在处理包含一页以上数据的实际 API 时,您不希望必须请求所有用户才能显示其中一页。您可能希望您的 DetailPage 组件通过他们的 ID 从像 https://jsonplaceholder.typicode.com/users/9 这样的 URL 请求特定用户。

    【讨论】:

      猜你喜欢
      • 2022-10-25
      • 2021-05-06
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      • 2021-05-10
      • 2021-05-25
      • 1970-01-01
      • 2020-02-21
      相关资源
      最近更新 更多