react中使用计算属性的三种方法(React computed)

前言

vue 中有 computed 计算属性这个概念,是非常好用的,不仅避免了人为 set 还具有及时响应的特点。

有了计算属性这个功能,可以很方便的对 props 进行一些中间处理,最后展示结果到视图上(或使用至需要的地方)。

在 react 中主要有三种使用 “计算属性” 的方法。

Class Component

对于类组件,直接使用 get 方法即可达成计算属性:

class ClassComponent extends Component {

  // 对于 props 的一些处理
  get computed() {
    return this.props.value
  }
  
  // 支持计算属性相互依赖
  // 在 vue 中,由于不支持 data 相互依赖,但支持 computed 相互依赖,这也是 vue 中非常好用的一点!
  get computed2() {
    return this.computed + '2'
  }

  render() {
    return (
      <div>{this.computed}, {this.computed2}</div>
    )
  }
}

function App() {

  const [state, setState] = useState('old')

  useEffect(() => {
    // 模拟一些异步处理,变化传入的 props
    setTimeout(() => {
      setState('new')
    }, 4000)
  }, [])

  return (
    <ClassComponent value={state}></ClassComponent>
  )
}

通过 class 的 get 方法,即可完成即时变化的计算属性,同时支持计算属性相互依赖。

Function Component

在函数组件中,一般使用 useMemo 进行计算属性的计算(当依赖列表变化时重新计算):

// 对 props 的处理函数
const handler = (v) => v

function FC({ value }) {

  // 通过依赖列表变化 useMemo 重新计算结果达到计算属性实时更新
  const computed = useMemo(() => handler(value), [value])

  return (
    <div>{computed}</div>
  )
}

function App() {

  const [state, setState] = useState('old')

  useEffect(() => {
    // 模拟一些异步处理,变化传入的 props
    setTimeout(() => {
      setState('new')
    }, 4000)
  }, [])

  return (
    <FC value={state}></FC>
  )
}

Function Component Async

当处理 props 的方法为异步时,useMemo 将不再适用,需要借用 useEffect 内部支持执行 async 函数的特性转化一步:

// 模拟异步处理 props 的逻辑
const asyncHandler = (v) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`已处理 ${v}`)
    }, 2000)
  })
}

/**
 * 处理 async 业务的 hooks 封装
 * @param {Function} func 异步逻辑函数
 * @param {Array} dep 依赖列表
 * @param {Object} initialValue 初始值
 */
function useAsyncComputed(func, dep, initialValue) {

  const [val, setVal] = useState(initialValue)
  
  // 借用 useEffect 执行异步逻辑
  useEffect(() => {
    let cancel = false

    const handler = async () => {
      const res = await func()

      if(!cancel) {
        setVal(res)
      }
    }
    handler()

	// 卸载时标记 cancel 已退出,在进程中的异步逻辑将不会再改变 val 值
    return () => {
      cancel = true
    }
  }, dep)

  return val
}

function AsyncFC({ value }) {

  const computed = useAsyncComputed(() => asyncHandler(value), [value], value)

  return (
    <div>{computed}</div>
  )
}

function App() {

  const [state, setState] = useState('old')

  useEffect(() => {
    // 模拟一些异步处理,变化传入的 props
    setTimeout(() => {
      setState('new')
    }, 4000)
  }, [])

  return (
    <AsyncFC value={state}></AsyncFC>
  )
}

在上文中我们封装了 useAsyncComputed 自定义 hooks 来处理含异步业务的计算属性,所以执行流程是:

  1. 初始显示传入的 value 值为 old

  2. 过 2 s 后,异步业务 asyncHandler 执行完毕,计算属性展示为 已处理 old

  3. 再过 2 s 后,传入的 props 改变为 new,触发异步业务 useAsyncComputed ,此时展示值仍为上一步的 已处理 old

  4. 再过 2 s 后,异步处理完毕,展示值为 已处理 new

实际处理中,可以增加 loading 效果,改进用户体验。

总结

以上方法是快速的在一个组件内达到计算属性效果,当然不限于此,还可以考虑全局状态管理 react-redux + redux-saga 来处理异步业务完成即时更新的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值