React+Typescript

函数组件

//推荐使用✅ better
const WrapComponent: React.FC<ExtendedProps> = (props) => {
// return ...
};
//直接使用
export default WrapComponent;

// 或者
export default function (props: React.PropsWithChildren<SpinProps>) {
// return ...
}
const Notice: React.FC = () => {}

forms

port * as React from 'react'

type changeFn = (e: React.FormEvent<HTMLInputElement>) => void

const App: React.FC = () => {

const [state, setState] = React.useState('')

const onChange: changeFn = e => {
setState(e.currentTarget.value)
}
✅ better
const onSubmit = (e: React.SyntheticEvent) => {
e.preventDefault()
const target = e.target as typeof e.target & {
password: { value: string }
} // 类型扩展
const password = target.password.value
}

return (
<form onSubmit={onSubmit}>
<input type="text" value={state} onChange={onChange} />
</form>
)

}

React Hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

useState

  • 调用useState() Hook 来启用函数组件中的状态。

  • useState(initialValue)的第一个参数initialValue是状态的初始值。

  • [state, setState] = useState(initialValue)返回一个包含2个元素的数组:状态值和状态更新函数。

  • 使用新值调用状态更新器函数setState(newState)更新状态。或者,可以使用一个回调setState(prev => next)来调用状态更新器,该回调将返回基于先前状态的新状态。

  • 调用状态更新器后,React 确保重新渲染组件,以使新状态变为当前状态。

    demo:按按钮新增灯泡或者开关灯

  • import React, { useState } from 'react'; function Bulbs() { const [on, setOn] = useState(false); const [count, setCount] = useState(1); const lightSwitch = () => setOn(on => !on); const addBulbs = () => setCount(count => count + 1); const bulb = <div className={on ? 'bulb-on' : 'bulb-off'} />; const bulbs = Array(count).fill(bulb); return ( <> <div className="bulbs">{bulbs}</div> <button onClick={lightSwitch}>开/关</button> <button onClick={addBulbs}>添加灯泡</button> </> ); }

//给定初始化值情况下可以直接使用

import { useState } from 'react';
// ...
const [val, toggle] = useState(false);
// val 被推断为 boolean 类型
// toggle 只能处理 boolean 类型


//没有初始值(undefined)或初始 null

type AppProps = { message: string };
const App = () => {
    const [data] = useState<AppProps | null>(null);✅ better
    // const [data] = useState<AppProps | undefined>();
    return <div>{data?.message}</div>;
};

useEffect

你之前可能已经在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount 具有相同的用途,只不过被合并成了一个 API。(我们会在使用 Effect Hook 里展示对比 useEffect 和这些方法的例子。)

可以把 useEffect Hook 看做 componentDidMountcomponentDidUpdatecomponentWillUnmount 这三个函数的组合。

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。

  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。

下面这个组件在 React 更新 DOM 后会设置一个页面标题:

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 使用浏览器的 API 更新页面标题
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

当你调用 useEffect 时,就是在告诉 React 在完成对 DOM 的更改后运行你的“副作用”函数。由于副作用函数是在组件内声明的,所以它们可以访问到组件的 props 和 state。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候。