Помещение функции выборки в отдельный компонент - PullRequest
2 голосов
/ 31 марта 2019

Я пытаюсь извлечь функцию 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 * 1011. * вот так:

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;

Далее я взял setIsLoaded (true); из api.js и вставил его в компонент Collage следующим образом:

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

Теперь я могу импортировать fetchImages в компонент Collage.

Однако я не знаю, что мне делать с этой строкой внутри функции fetchImages? Для этого нужно перейти к компоненту Collage, но res.data не определено внутри компонента Collage.

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

Как мне с этим справиться?

Ответы [ 2 ]

2 голосов
/ 01 апреля 2019

Есть много способов сделать это, но в вашем случае.Вы должны использовать

 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;

И в вашем компоненте Коллаж:

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

useEffect(() => {
  fetchImages(afterComplete);
}, []);
0 голосов
/ 31 марта 2019

Что вы можете сделать, это создать пользовательский хук (вроде HOC) ... Поскольку у меня нет ключа API unsplash, я приведу вам пример с другим 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

...