将提取功能放在单独的组件中

时间:2019-03-31 20:11:46

标签: reactjs react-hooks

我正试图从以下组件中取出 fetchImages 函数并将其放入新组件中:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import UnsplashImage from './UnsplashImage';

const Collage = () => {
  const [images, setImages] = useState([]);
  const [loaded, setIsLoaded] = useState(false);

  const fetchImages = (count = 10) => {
    const apiRoot = 'https://api.unsplash.com';
    const accessKey =
      '<API KEY>';

    axios
      .get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
      .then(res => {
        console.log(res);
        setImages([...images, ...res.data]);
        setIsLoaded(true);
      });
  };

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

  return (
            <div className="image-grid">
              {loaded
                ? images.map(image => (
                    <UnsplashImage
                      url={image.urls.regular}
                      key={image.id}
                      alt={image.description}
                    />
                  ))
                : ''}
            </div>
  );
};

export default Collage;

为此,我创建了一个名为 api.js 的新组件,从上述组件中删除了整个 fetchImage 函数,并将其放入 api.js中像这样:

api.js

    const fetchImages = (count = 10) => {
        const apiRoot = 'https://api.unsplash.com';
        const accessKey =
          '<API KEY>';

        axios
          .get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
          .then(res => {
            console.log(res);
            setImages([...images, ...res.data]);
            setIsLoaded(true);
          });
      };

export default fetchImages;

接下来,我从 api.js 中获取了 setIsLoaded(true); ,并将其粘贴到Collage组件中,如下所示:

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

现在我可以将 fetchImages 导入到Collage组件中。

但是,我不知道该如何在fetchImages函数中使用此行?这需要转到Collage组件,但是 res.data 未在Collage组件内定义。

setImages([...images, ...res.data]);

我应该如何处理?

2 个答案:

答案 0 :(得分:2)

有很多方法可以做到这一点,但就您而言。 您应该使用

 const fetchImages = (afterComplete, count = 10) => {
  const apiRoot = 'https://api.unsplash.com';
  const accessKey = '<API KEY>';

  axios
    .get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
    .then(res => {
      console.log(res);
      afterComplete(res.data);
    });
};

export default fetchImages;

在您的Collage组件中:

const afterComplete = (resData) =>{
  setImages([...images, ...resData]);
  setIsLoaded(true);
}

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

答案 1 :(得分:0)

您可以做的是创建一个自定义钩子(有点像HOC)...由于我没有unsplash API密钥,因此我将为您提供一个使用其他API的示例,但想法是相同的:

这是您的自定义钩子:

import { useState, useEffect } from 'react';

export const useFetch = url => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  const fetchUser = async () => {
    const response = await fetch(url);
    const data = await response.json();
    const [user] = data.results;
    setData(user);
    setLoading(false);
  };

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

  return { data, loading };
};

这里是如何在组件中使用它:

import { useFetch } from './api';

const App = () => {
  const { data, loading } = useFetch('https://api.randomuser.me/');

  return (
    <div className="App">
      {loading ? (
        <div>Loading...</div>
      ) : (
        <>
          <div className="name">
            {data.name.first} {data.name.last}
          </div>
          <img className="cropper" src={data.picture.large} alt="avatar" />
        </>
      )}
    </div>
  );
};

这是现场演示:https://codesandbox.io/s/3ymnlq59xm