Как вызвать запрос выборки реакционного хука в функциональном компоненте для доступа к данным, а затем передать в компонент класса для сопоставления? - PullRequest
2 голосов
/ 25 февраля 2020

После огромного количества проб и ошибок для сложного проекта webGL я нашел решение, которое уменьшит объем работ по реинжинирингу, три js кода (от другого разработчика) и, поскольку этот проект чрезвычайно время ограничено, уменьшите количество необходимого времени. Стоит также отметить, что мой опыт этого ограничен, и я единственный разработчик, оставшийся в команде.

В настоящее время проект принимает большой массив случайных пользовательских данных, которые экспортируются из файла js, а затем потребляется здесь ...

import Users from "./data/data-users";

class UsersManager {
  constructor() {
    this.mapUserCountries = {};
  }

  init() {
    Users.forEach(user => {
      const c = user.country;

      if (!this.mapUserCountries[c])
        this.mapUserCountries[c] = { nbUsers: 0, users: [] };
      this.mapUserCountries[c].nbUsers++;
      this.mapUserCountries[c].users.push(user);
    });
  }

  getUsersPerCountry(country) {
    return this.mapUserCountries[country];
  }
}

export default new UsersManager();

Вот мой запрос на выборку.

import { useState, useEffect } from "react";

const FetchUsers = () => {
  const [hasError, setErrors] = useState(false);
  const [users, setUsers] = useState({});

  async function fetchData() {
    const res = await fetch(
      "https://swapi.co/api/planets/4/"
    );
    res
      .json()
      .then(res => setUsers(res))
      .catch(err => setErrors(err));
  }

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

  return JSON.stringify(users);
};

export default FetchUsers;

Я столкнулся с множеством проблем, так как UserManager является компонентом класса, и если я импортирую свои fetchUsers в этот файл, вызовите его и сохраните в переменной, например: const Users = fetchUsers (); это нарушает крючки.

Я хочу иметь возможность вернуть функцию, которая будет возвращать моих пользователей из базы данных в виде массива.

Затем его можно будет передавать в UserManager точно так же, как жестко закодированные данные и отображать их, чтобы их можно было обработать множеством других файлов.

Я смоделировал маленькие коды и коробка с тем, что поток будет в идеале, но я знаю, что мне нужно решение вне крючков ...

https://codesandbox.io/s/funny-borg-u2yl6

спасибо

--- РЕДАКТИРОВАТЬ ---

import usersP from "./data/data-users";

class UsersManager {
  constructor() {
    this.mapUserCountries = {};
    this.state = {
      users: undefined
    };
  }

  init() {
    usersP.then(users => {
      this.setState({ users });
    });
    console.log(usersP);
    this.state.users.forEach(user => {
      const c = user.country;
      if (!this.mapUserCountries[c])
        this.mapUserCountries[c] = { nbUsers: 0, users: [] };
      this.mapUserCountries[c].nbUsers++;
      this.mapUserCountries[c].users.push(user);
    });
  }

  getUsersPerCountry(country) {
    return this.mapUserCountries[country];
  }
}

export default new UsersManager();
console.log (UsersManager.js:16 Uncaught TypeError: Cannot read property 'forEach' of undefined
    at UsersManager.init (UsersManager.js:16)
    at Loader.SceneApp.onLoadingComplete [as callback] (App.js:39)
    at Loader.onAssetLoaded (index.js:20)
    at index.js:36
    at three.module.js:36226
    at HTMLImageElement.onImageLoad)

Ответы [ 2 ]

1 голос
/ 25 февраля 2020

Я исправил ваш пример с песочницей .

Вы не можете загружать пользователей синхронно (используя import), так как вам нужно сделать http-вызов для извлечения пользователей, чтобы асинхронно .

В результате вы можете извлекать пользователей в методе жизненного цикла componentDidMount и использовать переменную состояния для сохранения их после извлечения

0 голосов
/ 25 февраля 2020

Существует пара рекомендаций, которые помогут разделить функции, которые являются хуками, и функции, являющиеся компонентами (они выполняются большую часть времени):

1 Функции компонентов используют pascal регистр (начинаются с заглавной буквы) и всегда возвращать JSX.

2 Пользовательские функции Hooks обычно начинаются со слова «use» и никогда не возвращают JSX.

В вашем случае вы, вероятно, захотите создать собственную функцию Hooks, которая должна быть вызванным в компоненте;

function useUserData() {
  const [hasError, setErrors] = useState(false);
  const [users, setUsers] = useState({});

  const networkCall = useCallback(async fetchData = () => {
    const res = await fetch(
      "https://swapi.co/api/planets/4/"
    );
    res
      .json()
      .then(res => setUsers(res))
      .catch(err => setErrors(err));
  } , [])

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

  return {users, hasError};
}

Затем вызвать эту настраиваемую ловушку в одном из ваших компонентов:

function App() {
  const {users, hasError} = useUserData();

    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <div>{users}</div>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    );
  }
}

Если затем вам нужно поделиться этими извлеченными данными во всем приложении, вы можете передать его через реквизит или контекстный API: https://reactjs.org/docs/context.html (опубликуйте сообщение, если хотите пример этого).

...