【问题标题】:Child React Component Always One Update Behind子 React 组件总是落后一个更新
【发布时间】:2020-09-02 16:51:40
【问题描述】:

我有一个父组件和一个子组件。

父组件将新图像上传到 API。子组件显示从同一 API 返回的图像列表。

我面临的问题是子组件总是落后一个更新。也就是说,将单个图像上传到父组件不会刷新它,但会更新第二个图像。添加第三张图片将显示前两张图片,但不显示第三张,以此类推。

父组件

function MediaLibrary(props) {
const [imageUploaded, setImageUploaded] = useState('');
const imagesGateway = ImagesGateway();

const handleUploadImage = async (event) => {
    event.preventDefault();

    let formdata = new FormData();
    formdata.append("image", event.target.files[0]);

    await imagesGateway.postArticleImages(props.articleId, formdata);

    // Update Files uploaded to try to trigger a refresh
    setImageUploaded(Math.random); 
}

return (
    <Container className="pt-4">
        <MediaList articleId={props.articleId} refresh={imageUploaded} />
        <Form.File
            id="articleImage"
            label="Upload Image"
            custom
            onChange={handleUploadImage}
        />
    </Container>
)

导出默认媒体库;

子组件

function MediaList(props) {
    const [images, setImages] = useState([]);
    const [loading, setLoading] = useState(true);
    const imageGateway = ImageGateway();

    useEffect(() => {
        fetchImages();
    }, [props]);

    const fetchImages = async () => {
        setLoading(true);
        const articleImages = await imageGateway.getArticleImages(props.articleId);
        setImages(articleImages);
        setLoading(false);
    }

    return (
        <Container>
            <Row>
                {images.map(image => (
                    <Image src={image} thumbnail />
                ))}
            </Row>
        </Container>
    )
}

export default MediaList;

编辑:看起来子组件中的 fetchimages 函数每次都会被来自 API 的正确数据命中,但这并没有触发子组件显示新数据。

【问题讨论】:

  • 你可以尝试解构child's useEffect [ ...props ]中的道具吗?
  • 顺便说一句,imagesGateway.postImage(formdata); 很可能是异步的,所以请await 让它首先使用async/await 函数或与then 链接它然后执行setImageUploaded(event.target.files[0].name);
  • 谢谢。我进行了建议的更改,并根据我的发现更新了上述内容。
  • 我觉得你还是要试试第一条评论里的...props,因为传递props引用是不行的,所以你需要监听props里面的属性

标签: reactjs react-hooks


【解决方案1】:

你有没有尝试过这样的方法:

父组件

import React, { useState } from "react";
import MediaList from "./MediaList";

export default function App() {
  const [loading, setLoading] = useState(false);
  const [images, setImages] = useState([]);
  const imagesGateway = ImagesGateway();

  const handleUploadImage = async (event) => {
    event.preventDefault();

    let formdata = new FormData();
    formdata.append("image", event.target.files[0]);

    await imagesGateway.postArticleImages(props.articleId, formdata);

    // Call fetchImages() everytime when you post something new
    fetchImages();
  };

  const fetchImages = async () => {
    setLoading(true);
    const articleImages = await imageGateway.getArticleImages(props.articleId);
    setImages(articleImages);
    setLoading(false);
  };

  return (
      <Container className="pt-4">
        <MediaList images={images} />
        
        <Form.File
          id="articleImage"
          label="Upload Image"
          custom
          onChange={handleUploadImage}
        />
      </Container>
  );
}

子组件

import React from "react";

function MediaList(props) {
  // Gettings images from props
  const { images } = props;

  return (
    <ul>
      {images.map((image) => (
        <li>
          {image.title}
          <img src={image} alt="img" />
        </li>
      ))}
    </ul>
  );
}

export default MediaList;

【讨论】:

    【解决方案2】:

    如下更新您的子组件,让您的组件正确地受到 refresh 属性更改的影响:

    function MediaList({ articleId, refresh }) {
        const [images, setImages] = useState([]);
        const [loading, setLoading] = useState(true);
        const imageGateway = ImageGateway();
    
        useEffect(() => {
            fetchImages();
        }, [refresh]);
    
        const fetchImages = async () => {
            setLoading(true);
            const articleImages = await imageGateway.getArticleImages(articleId);
            setImages(articleImages);
            setLoading(false);
        }
    
        return (
            <Container>
                <Row>
                    {images.map(image => (
                        <Image src={image} thumbnail />
                    ))}
                </Row>
            </Container>
        )
    }
    
    export default MediaList;
    

    【讨论】:

      猜你喜欢
      • 2021-11-10
      • 2021-06-04
      • 2021-04-09
      • 2020-07-08
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 2020-02-29
      相关资源
      最近更新 更多