转载请注明出处: http://qiudeqing.com/react/2022/09/12/note.html

表单

formik表单处理框架

代码分割

import()

引入代码分割最佳方式是通过动态import()

之前模式:

import { add } from './math'
console.log(add(16, 26))

使用之后:

import('./math')
  .then(math => {
    console.log(math.add(16, 26))
  })

webpack解析该语法时会自动进行代码分割。Create React App已配置该功能,Next.js已支持切无需配置。

React.lazy

React.lazy支持想渲染常规组件一样处理动态引入(的组件)

import OtherComponent from './OtherComponent'

使用之后:

const OtherComponent = React.lazy(() => import('./OtherComponent'))

代码会在组件首次渲染时,自动导入包含OtherComponent组件的包。

React.lazy接受一个函数,这个函数需要动态调用import()。它必须返回一个Promise,该Promise需要resolve一个default export的React组件。

然后在Suspense组件中渲染lazy组件,如此使得我们可以使用在等待加载lazy组件时做优雅降级(如loading提示器等)

import React, { Suspense } from 'react'

const OtherComponent = React.lazy(() => import('./OtherComponent'))

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  )
}

fallback属性接受任何在组建过程中你想展示的React元素。你可以将Suspense组件置于懒加载组件之上的任何位置。

默认情况下组件切换会显示兜底组件,使用startTransitionAPI可以在切换之前显示旧组建而不是兜底UI。

import React, { Suspense } from 'react'
import Tabs from './Tabs'
import glimmer from './Glimmer'

const Comments = React.lazy(() => import('./Comments'))
const Photos = React.lazy(() => import('./Photos'))

fucntion MyComponent() {
  const [tabs, setTab] = React.useState('photos')

  function handleTabsSelect(tab) {
    startTransition(() => {
      setTab(tab)
    })
  }

  return (
    <div>
      <Tabs onTabSelect={handleTabSelect}/>
      <Suspense fallback={<Glimmer />}>
        {tab === 'photos' ? <Photos /> : <Comments />}
      </Suspense>
    </div>
  )
}

异常捕获边界(Error boundaries)

useCallBack

useCallback is a React Hook that lets you cache a function definition between re-renders.

const cachedFn = useCallback(fn, dependencies)

export default function ProductPage({ productId, referrer, theme }) {
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    })
  }, [productId, referrer])
}

hooks

useContext

useContext is a React Hook that lets you read and subscribe to context from your component.

call useContext at the top level of your component to read and subscribe to context.

the context value is determined as the value passed to the closet SomeContext.Provider above the calling component in the tree. if there is no such provider, then the returned value will be the defaultValue you have passed to createContext for that context. The returned value is always up-to-date. React automatically re-renders components that read some context if it changed

import { useContext } from 'react'

function MyComponent() {
  const theme = useContext(ThemeContext)
}

function MyPage() {
  return (
    <ThemeContext.Provider value="dark">
      <MyComponent/>
    </ThemeContext.Provider/>
  )
}

function MyProviders({ children, theme, setTheme }) {
  const [currentUser, setCurrentUser] = useState(null)
  return (
    <ThemeContext.Provider value={theme}>
      <CurrentUserContext.Provide
        value=
      >
        {children}
      </CurrentUserContext.Provider>
    </ThemeContext.Provider>
  )
}

useMemo

useMeo is a React Hook that lets you cache the result of a calculation between re-renders.

const cachedValue = useMemo(calculateValue, dependencies)

const visibleTodos = useMemo(
  () => filterTodos(todos, tab),
  [todos, tab]
)

useState

const [state, setState] = useState(initialState)

React will store the next state, render your component again with the new values, and update the UI.

custom hooks

custom hooks let you share stateful logic but not state itself. Each call to a Hook is completely independent from every other call to the same Hook.

The code inside your comtom Hooks will re-run during every re-render of your component. This is why, like components, costom Hooks need to be pure. Think of Custom Hooks’ code as part of your component’s body.

Because custom Hooks re-render together with your component, they always receive the latest props and state.

most of your app’s Effects will be in custom Hooks.

Keep your custom Hooks focused on concrete high-level use cases.

benefit of wrapping Effects in custom hook:

Recap

function useFormInput(initialValue) {
  const [value, setValue] = useState(value)

  function handleChange(e) {
    setValue(e.target.value)
  }

  const inputProps = {
    value: value,
    onChange: handleChange,
  }

  return inputProps
}

const firstNameProps = useFormInput('mary')

<input {...firstNameProps} />