You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks与Fetch逻辑优化及Material-UI Card集成问题咨询

Hey there! Let's break down your code step by step—first looking at the implementation logic, then fixing that nested property rendering issue when switching to Material-UI Cards.

1. Feedback on Your Current Implementation Logic

  • Redundant Fetch Logic: You've got identical fetch calls in both useEffect and nextPerson. Extracting this into a reusable function will keep your code DRY (Don't Repeat Yourself), making maintenance easier if you ever need to adjust the API endpoint or add error handling.
  • Missing Loading State for Button Clicks: Right now, clicking the "click me" button doesn't trigger a loading state. Users might spam the button before new data loads, leading to unnecessary API calls. You should toggle the loading state here too.
  • Incorrect Key Placement: You're setting the key prop on the <img> element, but React expects the key to be on the root element returned by your map callback. This helps React efficiently update and re-render list items.
  • State Update Behavior: Your current setItems(response.results) replaces the entire items array with the new user. If your goal is to add users to the list instead of replacing them, use setItems(prev => [...prev, ...response.results]). If replacing is intentional, that's totally fine—just wanted to flag this as a configurable behavior!
  • No Error Handling: There's no fallback for failed fetch calls. Adding a .catch() block will prevent silent failures and let you notify users if something goes wrong.

2. Fixing the Nested Property Rendering Issue with Material-UI Cards

The problem where {item.something.something} won't render is likely due to either incorrect key placement or missing loading state handling during button clicks. Let's rewrite your component with Material-UI's Card components to fix this, while addressing the feedback above.

Updated Code with Material-UI Cards

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

const useStyles = makeStyles({
  root: {
    minWidth: 275,
    margin: '1rem auto',
    maxWidth: 300,
    boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
  },
  media: {
    height: 200,
    backgroundSize: 'contain',
    backgroundColor: '#f5f5f5',
  },
  content: {
    textAlign: 'center',
  },
  button: {
    marginTop: '1rem',
    width: '100%',
  },
});

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

  // Reusable function for fetching random users
  const fetchRandomUser = () => {
    setLoading(true); // Trigger loading state immediately
    fetch("https://randomuser.me/api") 
      .then((response) => {
        if (!response.ok) throw new Error('Failed to load user data');
        return response.json();
      })
      .then((response) => {
        // Replace existing user: setItems(response.results)
        // Uncomment below to add users to the list instead of replacing
        // setItems(prev => [...prev, ...response.results]);
        setItems(response.results);
        setTimeout(() => setLoading(false), 1000); // Keep loading animation
      })
      .catch(err => {
        console.error(err);
        setLoading(false);
        // Optional: Show an error message to the user here
      });
  };

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

  if (loading) { 
    return <div style={{ textAlign: 'center', marginTop: '2rem', fontSize: '1.2rem' }}>Loading ...</div>; 
  }

  return ( 
    <div style={{ padding: '1rem', maxWidth: '1200px', margin: '0 auto' }}>
      {items.map((item, i) => ( 
        // Key is placed on the root Card element (correct React practice)
        <Card className={classes.root} key={i}>
          <CardMedia
            className={classes.media}
            image={item.picture.large}
            alt={`${item.name.first} ${item.name.last}`}
          />
          <CardContent className={classes.content}>
            <Typography variant="h5" component="h2" gutterBottom>
              {item.name.first} {item.name.last}
            </Typography>
            <Typography color="textSecondary" variant="body1" gutterBottom>
              {item.email}
            </Typography>
            <Typography variant="body2" component="p">
              {item.location.city}, {item.location.country}
            </Typography>
            <Button 
              variant="contained" 
              color="primary" 
              className={classes.button}
              onClick={fetchRandomUser}
            >
              Get New User
            </Button>
          </CardContent>
        </Card>
      ))}
    </div> 
  ); 
}

Key Fixes & Improvements:

  • Reusable Fetch Logic: fetchRandomUser handles all API calls, including loading state management and error handling.
  • Proper Key Placement: The key is now attached to the <Card> element (the root of each mapped item), following React's list best practices.
  • Material-UI Card Integration: Uses Card, CardMedia, and CardContent to build a polished social card layout, with seamless access to nested properties like item.name.first and item.picture.large.
  • Loading State for Button Clicks: Every button click triggers the loading state, preventing duplicate API requests.
  • Error Handling: Added a .catch() block to handle failed requests gracefully.

Now when you map over items, all nested properties should render correctly inside the Card components. If you want to accumulate users instead of replacing them, just swap the state update line in fetchRandomUser to use the spread operator with previous state.

内容的提问来源于stack exchange,提问作者GoOsT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:53:56