繁体   English   中英

反应钩子和 fetch() 建议

[英]React hooks and fetch() advice

我有一个组件可以获取一个随机人,将其保存到 state 变量数组中,并在映射到该数组后返回某些元素。 我的目标是使用头像和个人信息呈现“社交卡”,我想为此使用材质 UI CARD 组件。 另外,我想在这里获得有关我的逻辑的任何反馈,这是否是实现我所取得的成就的好方法。 setTimeout() 只在那里,所以我可以渲染一些加载 animation。 此外,当我尝试返回数组 map 内的完整卡组件时,我无法渲染 {item.something.something}

export default function SocialCardsfunction() {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);

  const classes = useStyles();

  const nextPerson = () => {
    fetch("https://randomuser.me/api")
      .then((response) => response.json())
      .then((response) => {
        setItems(response.results);
      });
  };
  
  useEffect(() => {
    fetch("https://randomuser.me/api")
      .then((response) => response.json())
      .then((response) => {
        setTimeout(() => {
          setItems(response.results);
          setLoading(false);
        }, 1000);
      });
  }, []);

  if (loading) {
    return <div>Loading ...</div>;
  } else {
    return (
      <div>
        {items.map((item, i) => {
          return (
            <div>
              <h2>{item.name.first}</h2>
              <img src={item.picture.large} alt='picture' key={i} />
              <button onClick={() => nextPerson()}>click me</button>
            </div>
          );
        })}
      </div>
    );
  }
}

const useStyles = makeStyles({
  root: {
    minWidth: 275,
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)",
  },
  title: {
    fontSize: 14,
  },
  pos: {
    marginBottom: 12,
  },
});

所做的更改

  1. 不要重复相同的代码,而是创建 function 并在 useEffect 中调用useEffect
  2. 列表中的每个孩子都应该有一个唯一的“ key ”道具。
  3. 使用 Material UI 中的卡片。(我没有过多关注样式 XD)
import {
  Button,
  Card,
  CardActions,
  makeStyles,
} from "@material-ui/core";
import React, { useEffect, useState } from "react";

export default function SocialCardsfunction() {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);

  const classes = useStyles();

  const fetchPerson = () => {
    fetch("https://randomuser.me/api")
      .then((response) => response.json())
      .then((response) => {
        setTimeout(() => {
          setItems(response.results);
          setLoading(false);
        }, 1000);
      });
  };

  useEffect(() => {
    fetchPerson();
  }, []);

  if (loading) {
    return <div>Loading ...</div>;
  } else {
    return (
      <div>
        {items.map((item, i) => {
          return (
            <div key={i}>
              <Card className={classes.root}>
              <h2>{item.name.first}</h2>
                <img
                  alt="img"
                  src={item.picture.large}
                  className={classes.large}
                />
                <CardActions>
                  <Button onClick={() => fetchPerson()} size="small">Next</Button>
                </CardActions>
              </Card>
           
            </div>
          );
        })}
      </div>
    );
  }
}

const useStyles = makeStyles({
  root: {
    minWidth: 275
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)"
  },
  title: {
    fontSize: 14
  },
  pos: {
    marginBottom: 12
  }
});

您的逻辑看起来不错,但总有一些可以进一步改进的地方。

如果您只想在SocialCard中一次存储一个用户,那么我将只从 API 而不是列表中提取一个用户,因为 API 无论如何都会返回一个仅包含一个 ZA8CFDE6331BD59EB2AC96F8911C4B666 的数组。

首先,我将更改 state 并包括statuserror 使用status ,您可以轻松检查您的组件当前处于哪个状态,并根据该状态在您的应用程序中呈现不同的事物/消息。 使用error ,您可以定义自己的错误以防出现问题,然后在您的应用程序中呈现错误消息。 另外,我重新使用了您的 fetch,因为它被使用了两次,而且是多余的。 这样你就有了一个很好的单个 function 可以在任何地方使用,同时还确保在获取结果时显示loading 我还使用 MaterialUI Card组件来呈现用户数据。 您可以在此处查看结果的样子

import React, { useState, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import CardMedia from "@material-ui/core/CardMedia";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";

const useStyles = makeStyles({
  root: {
    maxWidth: 345
  }
});

function App() {
  const classes = useStyles();
  const [state, setState] = useState({
    user: {},
    status: "idle",
    error: null
  });
  const { user, status, error } = state;

  const getUser = () => {
    setState((prevState) => ({
      ...prevState,
      status: "loading"
    }));

    fetch("https://randomuser.me/api").then(async (res) => {
      if (res.ok) {
        const data = await res.json();

        setState((prevState) => ({
          ...prevState,
          user: data.results[0],
          status: "processed"
        }));
      } else {
        setState({
          user: {},
          status: "failed",
          error: "Error message"
        });
      }
    });
  };

  useEffect(() => {
    getUser();
  }, []);

  if (status === "loading") {
    return <div>Loading ...</div>;
  }
  if (status === "failed") {
    return <div>{error}</div>;
  }
  if (status === "processed") {
    return (
      <Card className={classes.root}>
        <CardActionArea>
          <CardMedia
            component="img"
            alt="user"
            height="140"
            image={user.picture.large}
            title="user"
          />
          <CardContent>
            <Typography gutterBottom variant="h5" component="h2">
              {user.name.first}
            </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small" color="primary" onClick={getUser}>
            Show another user
          </Button>
        </CardActions>
      </Card>
    );
  } else {
    // Default placeholder
    return <div>hi</div>;
  }
}

export default App;

但是,如果您想存储单击按钮时获取的所有用户,我建议将用户的 fetch 和 state 移动到父组件中,并保留SocialCard组件仅用于呈现单个用户。 然后,在父组件中,我将确保setStategetUser function 中看起来像这样

setState((prevState) => ({
  ...prevState,
  users: [...prevState.users, ...data.results], // This merges your previous user objects with new user object
  status: "processed"
}));

这样,您可以将所有用户保留在父组件中,并使用map您可以使用SocialCard组件呈现每个用户。 请注意,您需要进一步重构组件才能使其正常工作。 如果您想使用 go 这条路线,我会将其作为练习留给您。

暂无
暂无

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

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