React 函数组件

如何创建函数组件

  • 箭头函数形式
const Hello = (props) => { return <div>{props.message}</div> }
// 可以简写成
const Hello = props => <div>{props.message}</div>
  • function 形式
function Hello(props) {
  return <div>{props.message}</div>
}

函数组件 比 class组件 代码量少

看看这个例子,同样实现+1

class 组件

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      n: 1
    }
  }
  click = () => {
    this.setState(state => ({
      n: state.n + 1
    }))
  }
  render() {
    return (
      <div>
        {this.state.n}
        <button onClick={this.click}>+1</button>
      </div>
    )
  }
}

函数组件

const App = props => {
  const [n, setN] = useState(0)
  const click = () => {
    setN(n + 1)
  }
  return (
    <div>
      {n}
      <button onClick={click}>+1</button>
    </div>
  )
}

看来函数组件真的有很大的优势

可以用函数组件代替 class 组件吗?

面临两个问题

  • 函数组件没有 state
  • 函数组件没有生命周期

没有 State 怎么办?

React v16.8.0 推出 Hooks API,其中的一个 API 叫做 useState 可解决问题

import React, { useState } from 'react';

function Example() {
  // 声明一个叫 "count" 的 state 变量
  const [count, setCount] = useState(0);

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

没有生命周期怎么办?

React v16.8.0 推出 Hooks API,其中的一个 API 叫做 useEffect 可解决问题

  • 模拟 componentDidMount
useEffect(()=> { console.log('第一次渲染') }, [])
// 第个参数是 [] 时,函数只在开始时执行一次

useEffect 的第二个参数是需要监听的state属性,如果省略代表监听所有state属性的变化,如果是空,则代表不监听任何state属性

如果指定了需要监听的 state 对象,那么就只会监听这一个 state 属性。其他属性的变化,不会触发函数的执行

  • 模拟 componentDidUpdate
useEffect(() => { console.log('任意属性变更') })
useEffect(()=> { console.log('n变了') }, [n])
// 不传入第二个参数时,监听全部属性
// 传入 [n] 时,只监听 n 

但是这样并不能真正模拟 componentDidUpdate,因为它不会在第一次渲染时执行,而上面的代码无法做到这一点

所以为了修改这个问题,我们需要增加一些代码

const [nUpdateCount, setNUpdateCount] = useState(0)
  useEffect(() => {
    setNUpdateCount(nUpdateCount => nUpdateCount + 1)
  }, [n])
  useEffect(() => {
    if (nUpdateCount > 1) {
      console.log('更新了一次')
    }
  }, [nUpdateCount])

我们可以通过 nUpdateCount 来解决这个问题,nUpdateCount 检测到 n 的第一次变化,重 0 变为 1,而 useEffect 中判断 nUpdateCount 大于 1 时,才开始执行

但是这样的代码似乎还是有点繁琐,还可以继续优化

写成一个 useUpdate 函数,fn 是更新时执行的函数,dey是监听对象,这个函数可以从组件中提取处理,使用时直接应用

const useUpdate = (fn, dey) => {
  const [count, setCount] = useState(0)
  useEffect(() => {
    setCount(count => count + 1)
  }, [dey])
  useEffect(() => {
    if (count > 1) {fn()}
  }, [count, fn])
}

组件中直接调用 useUpdate

useUpdate(() => {console.log('更新了一次')}, n)
  • 模拟 componmentWillUnmount
useEffect(() => {
  console.log('数据更新了')
  return () => {
    console.log("我要被销毁了")
  }
})

useEffect可以再返回一个函数,他会在组件消失时调用,而console.log('数据更新了')则会在组件发生变化重渲染时调用

  • 模拟 shouldComponentUpdate
const MyComponent = React.memo(
    _MyComponent, 
    (prevProps, nextProps) => nextProps.count !== prevProps.count
)

React.memo 包裹一个组件来对它的 props 进行浅比较,但这不是一个 hooks,因为它的写法和 hooks 不同,其实React.memo 等效于 PureComponent,但它只比较 props。

上一篇:Android API Guides – Introduction to Android


下一篇:RHEL5使用multipath配置ASMdisk