Я пытаюсь сделать Load More в списке данных, как написано ниже:

import React, { useState, useEffect } from "react";
import { render } from "react-dom";
import axios from "axios";
import "./style.css";

const App = () => {
  const LIMIT = 2;
  const [data, setData] = useState([]);
  const [isLoading, setLoading] = useState(false);
  const [page, setPage] = useState(1);

  const loadData = async (skip = 1, limit = LIMIT) => {
    const URL = "https://reqres.in/api/users";
    const headers = {
      "Content-Type": "application/json",
      Accept: "application/json"
    };

    const params = {
      page: skip,
      per_page: limit
    };

    const a = await axios.get(URL, { params, headers });
    // const b = [...new Set([...data, ...a.data.data])]; <-- setting this will thrown error
    setData(a.data.data);
    setLoading(false);
  };

  useEffect(() => {
    setLoading(true);
    loadData(page);
  }, [page]);

  useEffect(() => {
    console.log("page", page, "data", data.length);
  }, [page, data]);

  const doReset = evt => {
    evt.preventDefault();
    setPage(1);
  };

  const doLoadMore = evt => {
    evt.preventDefault();
    setPage(page + 1);
  };

  return (
    <div className="container">
      <h1>Listing</h1>
      <button className="btn text-primary" onClick={evt => doReset(evt)}>
        Reset
      </button>
      <button className="btn text-primary" onClick={evt => doLoadMore(evt)}>
        Load More
      </button>
      {isLoading && <p>Loading..</p>}
      {!isLoading && (
        <ul>
          {data.map(a => (
            <li key={a.id}>
              {a.id}. {a.email}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

render(<App />, document.getElementById("root"));

Полностью рабочий пример можно найти здесь. Я думаю, что этот код должен работать, но это не так.

const a = await axios.get(URL, { params, headers });
const b = [...new Set([...data, ...a.data.data])];
setData(b);

Поэтому, пожалуйста, помогите, как сделать Load More в React Hooks?

0
hbinduni 7 Окт 2019 в 17:15

2 ответа

Лучший ответ

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

import React, { useState, useEffect, useCallback } from "react";
import axios from "axios";

import Navbar from "./Navbar";

const App = () => {
  const LIMIT = 2;
  const [tube, setTube] = useState([]);
  const [data, setData] = useState([]);
  const [isLoading, setLoading] = useState(false);
  const [page, setPage] = useState(1);

  const loadData = useCallback(
    async (limit = LIMIT) => {
      setLoading(true);
      const URL = "https://reqres.in/api/users";
      const headers = {
        "Content-Type": "application/json",
        Accept: "application/json"
      };

      const params = {
        page,
        per_page: limit
      };

      const a = await axios.get(URL, { params, headers });
      if (!a.data.data) {
        return;
      }

      setData(a.data.data);
      setLoading(false);
    },
    [page]
  );

  useEffect(() => {
    if (!isLoading) {
      return;
    }
    setTube([...new Set([...tube, ...data])]);
  }, [data, isLoading, tube]);

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

  useEffect(() => {
    console.log("page", page, "data", data.length);
  }, [page, data]);

  const doLoadMore = evt => {
    evt.preventDefault();
    setPage(page + 1);
  };

  return (
    <>
      <Navbar />

      <main role="main" className="container">
        <div className="starter-template text-left">
          <h1>Listing</h1>
          <button className="btn text-primary" onClick={evt => doLoadMore(evt)}>
            Load More
          </button>
          <ul>
            {tube &&
              tube.map(a => (
                <li key={a.id}>
                  {a.id}. {a.email}
                </li>
              ))}
          </ul>
          {isLoading && <p>Loading..</p>}
        </div>
      </main>
    </>
  );
};

export default App;

Также я обнаружил, что может быть намного проще просто применить это eslint-disable-next-line react-hooks/exhaustive-deps, чтобы компилятор проигнорировал предупреждение. что-то вроде этого.

useEffect(() => {
    setConfig({...config, params: {...params, skip}});
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [skip]);

Для получения информации можно найти по этому:

0
hbinduni 8 Окт 2019 в 00:19

Я получил ваш пример на работу, изменив на это:

const b = [...data, ...a.data.data];
setData(b);
1
Brian Thompson 7 Окт 2019 в 14:58