簡體   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