ReactJS: Загрузка элементов из api и распределение в блоки

Новичок в JS. Есть такие задачи: 1) загрузку пользователей 2) отображения списка месяцев 3) подсветить месяца в зависимости от количества людей, которые родились в этом месяце. 4) при наведении на выбранный месяц - отобразить список людей, родившихся в этом месяце. К сожалению, я застрял после импорта пользователей из API. Извините за банальный вопрос:- Каким методом распределить пользователей в блоки (месяцы рождения) и вывести jsx? большое спасибо

function App() {
  const [users, setUser] = useState(null);

  const fetchData = async () => {
    const response = await axios.get(
      'https:...api/users'
    );

    setUser(response.data);
  };

  return (
    <div className="App">
      <h1>Users list</h1>


      {/* Fetch data from API */}
      <div>
        <button className="fetch-button" onClick={fetchData}>
          download users
        </button>
        <br />
      </div>

      {/* Display data from API */}
      <div className="users">
        {users &&
          users.map((user, index) => {
            const cleanedDate = new Date(user.released).toDateString();
            const name = user.firstName;

            return (
              <div className="user" key={index}>
                <h3>user {index + 1}</h3>
                <h2>{user.name}</h2>

                <div className="details">
                  <p>👨id: {user.id}</p>
                  <p>firstName: {user.firstName}</p>
                  <p>lastName: {user.lastName}</p>
                  <p>⏰: {user.dob}</p>
                </div>
              </div>
            );
          })}
      </div>

    </div>
  );
}

пример элемента юзера { “id”: “5e00928d43fcdd11688a6afd”, “firstName”: “Moody”, “lastName”: “Gordon”, “dob”: “2019-11-09T20:20:43.744Z” }

Основная загвоздка здесь в том, что на входе у тебя пользователи, а на выходе должны быть месяцы. Тут тебе поможет reduce.
Попробуй что-нибудь вроде

const months = users.reduce((acc, user) => {
	const month = // извлечь нужный месяц из пользователя
	if (acc[month]) {
		acc[month].push(user);
	} else {
		acc[month] = [user];
	}

	return acc;
}, {});

тогда у тебя на выходе получится вот такой объект:

{
	'January': [{firstName: 'XXX', lastName: 'YYY'}, { firstName: "ZZZ", lastName: 'AAA'}],
}

И его ты сможешь показать в виде списка.

2 лайка

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

const appModel = []

Разумеется это должен быть результат useState. Массив appModel моделирует связь месяца и пользователей. Индекс элемента массива - это номер месяца, значение - массив пользователей которые родились в этом месяце.

Пример возможного appModel:

const appState = [
	[{ "id": "5e00928d43fcdd11688a6afe", "firstName": "Boody", "lastName": "Lol", "dob": "2019-01-09T20:20:43.744Z" }],
	[],
	[],
	[],
	[],
	[],
	[],
	[],
	[],
	[],
	[{ "id": "5e00928d43fcdd11688a6afd", "firstName": "Moody", "lastName": "Gordon", "dob": "2019-11-09T20:20:43.744Z" }],
	[],
]

Теперь твоя задача сводится к тому чтобы

  1. Преобразовать структуру данных из API ответа в структуру выше.
  2. Отрендерить. map судя по примеру ты умеешь. В map-е у тебя будет и список месяцев и индекс месяца, следовательно будет и список пользователей. Останется сгенерировать скрытый div со списком пользователей и показывать его нa hover элемента месяца календаря.
1 лайк

Ребят, спасибо. но при выполнения пунктов 3) подсветить месяца в зависимости от количества людей, которые родились в этом месяце. и
4) при наведении на выбранный месяц - отобразить список людей, родившихся в этом месяце возникла проблема с доступом к ключу объекта, который является элементом массива Безымянный

//Не получается получить доступ к массиву(ключу) users в объектах массива groupedUsers
К какому элементу(массиву обращаться) для смены цветов блоков в зависимости от кол-ва юзеров, а также выводу их при наведении? Если все же к users, то как грамотно построить функция Object.keys для корректной ее отработки в данном случае?

Еще раз спасибо!

import React, { useState } from ‘react’;
import ReactDOM from ‘react-dom’;
import axios from ‘axios’;
import ‘./styles.css’;
import classes from ‘./components/Month/month.module.css’

function App() {
const [users, setUser] = useState(null);
const cls = [];

const fetchData = async () => {
const response = await axios.get(
https://yalantis-react-school.herokuapp.com/api/task0/users
);

setUser(response.data);

};
const groupedUsers = users && users.reduce((acc, n) => {
acc[new Date(n.dob).getMonth()].users.push(n);
return acc;

}, […Array(12)].map((n, i) => ({
month: new Date(0, i).toLocaleString(‘ru-RU’, { month: ‘long’ }),
users: [],

}))
);
if(this.groupedUsers.length > 2 ) {
cls.push(classes.month + ‘red’)
} else if (this.Array.length > 5) {
cls.push(classes.month + ‘green’)
};
//Не получается получить доступ к массиву(ключу) users в объектах массива groupedUsers

return (


Users list

  {/* Fetch data from API */}
  <div>
    <button className="fetch-button" onClick={fetchData}>
      download users
    </button>
    <br />
  </div>

  {/* Display data from API */}
  <div className="users">
   {groupedUsers && groupedUsers.map(n => (

{n.month}

{n.users.map(user => (
    <div>
     <h4 className={classes.userId}>user #{user.id}</h4>
    данные пользователя...</div>
  </div>
))}
))}

Если ты хочешь получить доступ там, где ты у тебя написан комментарий:

То не получится, да и, как мне кажется, не нужно.

У тебя же есть:

там и получай.

А также, обрати внимание, что this.groupedUsers.length у тебя всегда будет равен 12 (если users присутствует).

2 лайка

Спасибо, добрый человек! Может подскажешь, как решить очередную дилемму:
Задача: вывести при наведении всех пользователей, которые родились в этом месяце. Переменная меняет значение в функции onHover, которая вызывается методом onMouseOver Пробовал и без использования .bind, ошибка не перестает преследовать:
TypeError: Cannot read property ‘onHover’ of undefined
Как пофиксить функцию onHover? Заранее спасибо!

https://jsfiddle.net/kw12ab94/

Ok, если правильно вижу, ты вызываешь там this.onHover. Что это и откуда оно берется?