5分钟学会 React Hooks
这些是什么?
跳进去👟
useState
为什么不上课?📗
其他钩子
useEffect
关注点分离
创建自定义钩子
应该做的事👍
注意事项👎
注意事项⚠️
就是这样!
这些是什么?
一组函数,为我们在实例上访问的方法提供直接 API Component。我们可以创建有状态组件,或者在没有实例的情况下访问组件的生命周期class🎉
对于那些TL;DR阵营的人来说,向下滚动查看一系列演示👍
跳进去👟
考虑一下这个选择并显示颜色值的应用程序🎨
我们需要一个class实例来添加state。
const colors = {
  Sea: '#a2ccb6',
  Sand: '#fc22b5',
  Peach: '#ee786e',
}
class App extends Component {
  state = {
    color: colors.Sea,
  }
  render = () => {
    const { color } = this.state
    return (
      <Fragment>
        <select
          value={color}
          onChange={e => this.setState({color: e.target.value})}
          >
          { Object.entries(colors).map(c => (
            <option key={`color--${c[0]}`} value={c[1]}>
              {c[0]}
            </option>
          ))}
        </select>
        <h2>{`Hex: ${color}`}</h2>
      </Fragment>
    )
  }
}
但带钩子
const { useState } = React
const App = () => {
  const [color, setColor] = useState(colors.Sea)
  return (
    <Fragment>
      <select value={color} onChange={e => setColor(e.target.value)}>
        {Object.entries(colors).map(([name, value]) => (
          <option value={value}>{name}</option>
        ))}
      </select>
      <h1>{`Hex: ${color}`}</h1>
    </Fragment>
  )
}
useState是一个允许我们使用和更新状态值的钩子。
useState
该useState钩子提供了一个状态值以及更新它的方法。参数是默认值。该值也可以是任意类型!👍
不需要class实例🙌
不要害怕这种语法。useState利用Array解构。
它等于
const state = useState(Colors.Sea)
const color = state[0]
const setColor = state[1]
为什么不上课?📗
- 缩小效果并不好。
- 当课程试图承担过多内容时,就会失去背景。
- 生命周期方法中的关注点分离不佳。
- 需要对属性进行不稳定的语法转换class。
- HMR 问题。
- 主观用例,何时使用而不是无状态函数。
如果课程适合您,则无需更改。Hooks 不会取代课程。
其他钩子
有几种钩子。你可能最常使用的钩子是useState和useEffect。其他钩子请参阅钩子参考。
useEffect
当我们想要进入生命周期阶段时,我们会使用这个钩子。
useEffect === componentDidMount + componentDidUpdate + componentWillUnmount
我们将一个函数传递给useEffect在每次渲染上运行的钩子。
让我们使用 来更新我们之前的颜色选择应用程序useEffect。
const App = () => {
  const [color, setColor] = useState(colors.Sea)
  useEffect(
    () => {
      document.body.style.background = color
    }
  )
  return (
    <Fragment>
      <select value={color} onChange={e => setColor(e.target.value)}>
        {Object.entries(colors).map(([name, value]) => (
          <option key={`color--${name}`} value={value}>
            {name}
          </option>
        ))}
      </select>
      <h1>{color}</h1>
    </Fragment>
  )
}
现在当状态更新时,主体颜色将会改变👍
每次渲染都会运行?没错。不过,它并非必须如此。 有一个可选的第二个参数useEffect。您可以传递一个Array值,如果这些值在渲染期间没有变化,则效果将不会执行。空Array表示效果只运行一次。但在大多数情况下,有更好的解决方案来实现这个结果,
useEffect(
  () => {
    document.body.style.background = color
  },
  [color]
)
现在我们只在发生变化时设置背景color👍在这个例子中,它仍然会运行每个渲染,因为这color是触发渲染的唯一事物。
如果我们有第二个状态值,我们就能看到这个可选参数的实际作用。让我们添加一个在按钮点击时递增的计数器值。
const App = () => {
  const [color, setColor] = useState(colors.Sea)
  const [count, setCount] = useState(0)
  // Only run when color is updated 👍
  useEffect(
    () => {
      console.info('Color changed')
      document.body.style.background = color
    },
    [color]
  )
  return (
    <Fragment>
      <select value={color} onChange={e => setColor(e.target.value)}>
        {Object.entries(colors).map(([name, value]) => (
          <option key={`color--${name}`} value={value}>
            {name}
          </option>
        ))}
      </select>
      <h1>{color}</h1>
      <h1>{`Count: ${count}`}</h1>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </Fragment>
  )
}
console.info仅当颜色改变时才会触发👍
其他效果(例如发出 API 请求或绑定用户输入)怎么样?
让我们制作一个跟踪鼠标移动的小应用程序。
我们利用useEffect绑定鼠标移动来更新一些状态值。
const App = () => {
  const [x, setX] = useState()
  const [y, setY] = useState()
  useEffect(
    () => {
      const update = (e) => {
        setX(e.x)
        setY(e.y)
      }
      window.addEventListener('mousemove', update)
    },
    []
  )
  return x && y ? (<h1>{`x: ${x}; y: ${y};`}</h1>) : null
}
如果组件卸载了,该如何清除绑定?我们可以从useEffect函数中返回一个函数来进行清理。
useEffect(
  () => {
    const update = (e) => {
      setX(e.x)
      setY(e.y)
    }
    window.addEventListener('mousemove', update)
    return () => {
      window.removeEventListener('mousemove', update)
    }
  },
  []
)
不错👊
关注点分离
钩子使我们能够更好地分离关注点。
您是否曾经见过class似乎有很多事情要做的生命周期方法?
componentDidMount = () => {
  makeSomeAPIRequest()
  makeOtherAPIRequest()
  bindTouchListener()
  bindClickEvents()
  doOtherUnrelatedStuff()
}
我们可以用钩子来避免这种情况。只要我们的钩子位于顶层,我们就可以随意使用。
考虑更新我们的应用,使其也监听resize事件。我们不需要在我们的mousemove效果中实现这一点。我们可以创建一个单独的效果。这是一个值得养成的好习惯,尤其是在我们开始创建自定义钩子的时候。
const App = () => {
  const [dimensions, setDimensions] = useState(getDimensions())
  const [x, setX] = useState()
  const [y, setY] = useState()
  // Effect for mousemove
  useEffect(
    () => {
      const update = e => {
        setX(e.x)
        setY(e.y)
      }
      window.addEventListener('mousemove', update)
      return () => {
        window.removeEventListener('mousemove', update)
      }
    },
    []
  )
  // Effect for window resizing
  useEffect(
    () => {
      const updateSize = () => setDimensions(getDimensions())
      window.addEventListener('resize', updateSize)
      return () => {
        window.removeEventListener('resize', updateSize)
      }
    },
    []
  )
  return (
    <Fragment>
      {x && y && <h1>{`x: ${x}; y: ${y};`}</h1>}
      <h1>
        {`Height: ${dimensions.height}; Width: ${dimensions.width};`}
      </h1>
    </Fragment>
  )
}
这是一个演示👍
创建自定义钩子
最后一个示例中的组件开始增长了。Hook 最棒的特性之一就是我们可以将其用法提取到自定义 hooks 中。
这是 Hooks 的一大卖点。你可能对 props 很熟悉Higher Order Components。render我们经常需要某种难以维护或论证的结构或风格。但使用 Hooks 则不会出现这种情况。
考虑一下我们的例子。在我们的应用中,跟踪鼠标移动可能很常见。共享这种逻辑是理想的选择。那就开始吧!
const useMousePosition = () => {
  const [x, setX] = useState()
  const [y, setY] = useState()
  useEffect(
    () => {
      const update = e => {
        setX(e.x)
        setY(e.y)
      }
      window.addEventListener('mousemove', update)
      return () => {
        window.removeEventListener('mousemove', update)
      }
    },
    []
  )
  return { x, y }
}
注意我们新的自定义钩子是如何返回当前状态值的。现在任何组件都可以使用这个自定义钩子来获取鼠标位置。
const App = () => {
  const { x, y } = useMousePosition()
  return x && y ? <h1>{`x: ${x}; y: ${y};`}</h1> : null
}
现在我们有了可以在其他组件之间共享的逻辑💪
让我们考虑另一个例子。我们有各种各样的手表。它们看起来不同,但都使用相同的时间⌚️我们可以自定义一个钩子来获取时间。以下是一个例子;
应该做的事👍
- 当你需要连接到状态或生命周期阶段时使用
- 使用钩子分离关注点
注意事项👎
- 在循环中使用
- 将它们嵌套
- 根据条件使用它们。
注意事项⚠️
- 从react@16.7.0-alpha开始可用
- 没有重大变化🙌
- eslint-plugin-react-hooks@next 👍
就是这样!
5 分钟介绍 React Hooks!
进一步了解➡️
获取所有代码➡️
一如既往,如果您有任何问题或建议,请随时留言或发推文给我🐦!记得在社交媒体上关注我!😎
文章来源:https://dev.to/jh3y/react-hooks-in-5-minutes-55ic 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com
           
 
