Day28-Custom Hook

前言

我们学习了效能优化、生命周期、React状态等等,今天我们要来学习React的模组化,也就是custom hook。

  • use开头,若不使用use开头便无法辨识Hook的规则
  • React中允许内部使用其他Hooks
  • 把未来预期会重复使用的功能,包装成函式,达成重复利用。

useFetch

今天我们来把fetch包装成模组化。

前端会呼叫API的机会非常多,於是我们把fetch包装成一个模组。

以下为目前的资料夹状态,我们会在Hooks底下创建useFetch.js

https://ithelp.ithome.com.tw/upload/images/20210926/20130419AwuAyW1UaD.png

我们会先建立三个state,确认读取状态、资料、错误讯息

//useFetch.js
import {useEffect, useState} from 'react'

function useFetch(url) {
  const [isLoading, setIsLoading] = useState(false)
  const [data, setData] = useState('')
  const [error, setError] = useState('') 
  
  return {data, error, isLoading}
}
export default useFetch

基本状态定型後,使用useEffect来作为读取资料的副作用。

//useFetch.js
import {useEffect, useState} from 'react'

function useFetch(url) {
  const [isLoading, setIsLoading] = useState(false)
  const [data, setData] = useState('')
  const [error, setError] = useState('') 

  useEffect(() => {
    
  },[url]) 
  
  return {data, error, isLoading}
}

export default useFetch

接下来我们需要把逻辑放在useEffect中

我们所想的,当资料被塞入

  1. 把isLoading设为true,代表正在读取
  2. 把url中的资料转为json格式,并且塞入data state中
  3. 如果fetch状态为reject,把错误报告塞入error state中
  4. 最後把isLoading的状态设置为false
  5. 回传三个数值
//useFetch.js
import {useEffect, useState} from 'react'

function useFetch(url) {
  const [isLoading, setIsLoading] = useState(false)
  const [data, setData] = useState('')
  const [error, setError] = useState('') 

  useEffect(() => {
    setIsLoading(true)
    fetch(url)
    .then((res) => res.json())
    .then((json) => setData(json))
    .catch((err) => setError(err))
    .finally(() => setIsLoading(false))
  },[url])
  
  return {data, error, isLoading}
}

export default useFetch

回到App.js,要来引入API

我们使用这个fake api来模拟API

使用解构赋值把data、isLoading、error抓取出来

  const {data, isLoading, error} = useFetch('https://jsonplaceholder.typicode.com/todos/1')
//App.js
import useFetch from '../Hooks/useFetch'

function App() {
  const {data, isLoading, error} = useFetch('https://jsonplaceholder.typicode.com/todos/1')
  
  if (isLoading) {
    return <h1>isLoading....</h1>
  } else if (error) {
    return <h1>data can't fetch</h1>
  } else {
    return (
      <div>
        <p>{data.userId}</p>
        <p>{data.id}</p>
        <p>{data.title}</p>
      </div>
    )
  }
}

export default App

这样我们就可以很简单完成每次获取API的动作,也可以确保状态、跟资料是符合的。

最後我们再把Loading分成一个组件,避免App.js中太多元素。

https://ithelp.ithome.com.tw/upload/images/20210926/20130419c9v1JpE5GP.png

//Loading.js
import React from 'react'

function Loading() {
  return (
    <div>
      <h1>Loading...</h1>
    </div>
  )
}

export default Loading

//App.js
import useFetch from '../Hooks/useFetch'
import Loading from './Loading'
function App() {
  const {data, isLoading, error} = useFetch('https://jsonplaceholder.typicode.com/todos/1')
  
  if (isLoading) {
    return <Loading />
  } else if (error) {
    return <h1>data can't fetch</h1>
  } else {
    return (
      <div>
        <p>{data.userId}</p>
        <p>{data.id}</p>
        <p>{data.title}</p>
      </div>
    )
  }
}

export default App

基本上我们就完成React的核心思想,切分组件、避免耦合性高、重复利用的技巧了!!!

/images/emoticon/emoticon01.gif


<<:  理解网际网路协定(三):何谓「子网路遮罩」,什麽又是「预设闸道」?

>>:  ESP32_DAY11 短路

仿Trello - 前端 Apollo Client 串接 GraphQL API

本系列文以制作专案为主轴,纪录小弟学习React以及GrahQL的过程。主要是记下重点步骤以及我觉...

第二十八天:文字排版

金鱼都能懂的网页切版:22、23、24、25 文字排版 在文字排版里,html版面基本是一模一样,只...

[影片]第28天:英雄指南-5. 新增应用内导航(3)

GitHub:https://github.com/dannypc1628/Angular-Tou...

【Day 7】Replica 的 Quorum 、State machine replication

5.2 Quorum read-after-write(read-your-write) consi...

css 阴影

今天要来说说如何为一个div加上阴影,我们先来看看效果如何,我创造出一个橘色的方块,并且在他的css...