React Suspense + Custom Hook открывает новый способ запроса данных.

React.js

мимо

компонент класса

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

class App extends Component {
  state = {
    loading: false,
  }

  componentDidMount() {
    this.setState({
      data: null,
      loading: true,
    });
    axios.get('/api/test').then((data) => {
      this.setState({
        data,
        loading: false,
      });
    });
  }

  render() {
    return this.state.loading ? '正在加载中...' : (
      <Page data={data} />
    );
  }
}

крюк в сборе

const useRequest = (fn, dependencies = []) => {
  const [data, setData] = useState(defaultValue);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    
    fn()
      .then(res => {
        setData(res);
      })
      .finally(() => {
        setLoading(false);
      });
  }, dependencies);

  return { data, setData, loading };
};
// App.js
function App() {
  const { loading, data } = useRequest(() => axios.get('/api/test'));
  return loading ? '正在加载中...' : (
    <Page data={data} />
  );
}

будущее

Конкретный код можно найти здесь:код sandbox.io/yes/react-water-pollution…

// Router.js
import React, { Suspense } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Spin } from "antd";
import Author from "./Pages/Author";
import Table from "./Pages/Table";
import Layout from "./Layout";

export default function App() {
  return (
    <Router>
      <Layout>
        <Suspense fallback={<Spin tip="正在拼命获取数据,请稍后..." />}>
          <Switch>
            <Route exact path="/">
              <Author />
            </Route>
            <Route exact path="/table">
              <Table />
            </Route>
          </Switch>
        </Suspense>
      </Layout>
    </Router>
  );
}

// pages/Author
import React from "react";
import useSWR from "../use-swr";

export default function Author() {
  const { data } = useSWR("/api/user");

  return (
    <div>
      <span>Hello {data.userName}</span>
    </div>
  );
}
import useSWR from "swr";
import fetcher from "./fetcher";

export default url => {
  return useSWR(url, fetcher, { suspense: true });
};
// fetcher
const fetcher = url => {
  let responseData;

  switch (url) {
    case "/api/user":
      responseData = {
        userName: "ssh"
      };
      break;
    default:
      break;
  }

  return new Promise(resolve => {
    setTimeout(() => {
      resolve(responseData);
    }, 2000);
  });
};

export default fetcher;

На самом деле эта демонстрация используетсяswrЭта библиотека просто инкапсулирует элементы конфигурации и включает режим ожидания.

Fetcher, необходимый для второго параметра, является логикой, которая возвращает обещание, определенное сам по себе.

В этом режиме ожидания мы можем легко управлять состоянием загрузки, и нам не нужно заботиться и объявить нагрузочные компоненты в компоненте страницы.

оswrСтатью с конкретным анализом этой библиотеки можно найти здесь:Интенсивное чтение "Извлечение хуков - исходный код swr"

В этой демонстрации, если вы войдете снова после ввода маршрута, данные будут напрямую отображать ранее запрошенные данные.Вы обнаружите, что это очень похоже на то, что в Vue.keep-aliveЭффект в том, что библиотека swr кэширует данные по умолчанию в режиме ожидания, если вы хотите его отключить, вы не видели соответствующей конфигурации в документе.

Реализуйте простой useSWR самостоятельно

// use-my-swr
import { useState, useEffect } from "react";

export default (url, fetcher) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetcher(url)
      .then(result => {
        setData(result);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [url, fetcher]);

  if (loading) {
    throw Promise.resolve(null);
  } else {
    return { data };
  }
};

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

использовать:

import React from "react";
import useSWR from "../use-my-swr";
import fetcher from "../fetcher";

export default function Author() {
  const { data } = useSWR("/api/user", fetcher);

  return (
    <div>
      <span>Hello {data && data.userName}</span>
    </div>
  );
}

резюме

Эта статья — всего лишь небольшая закуска перед появлением Suspense.В ходе долгой разработки React разработчики испытали различные способы написания, HOC, render-props, хуки, и их конечная цель — на самом деле позволить нам писать код. читать и поддерживать, делая разработчиков как можно более счастливыми.

Hookа такжеSuspenseСталкиваясь вместе, внутренняя логика компонента полностью отделяется от запроса и внутреннего состояния ожидания, по сравнению с компонентами предыдущего класса код становится все более упорядоченным.

С нетерпением ждем дальнейших действий от команды React!

Справочная статья:

Интенсивное чтение "Извлечение хуков - исходный код swr"