react render propsGetter

529 阅读3分钟

前言

通过上篇的介绍,我们可以把一些常见的属性封装到一个辅助方法里,让我们对这部分的使用更加方便。

但这样并不是非常的完美,因为有些时候我们需要获取其部分属性,还有部分场景下可以追加自己的事件。

获取设置属性

比如之前的案例中,我们在toggle组件使用中,针对on属性需要显性的作为入参才可以使用,追加的onclick事件不但希望触发toggle事件,也希望可以进行自定义事件的触发

function Usage({
  onToggle = (...args) => console.log('onToggle', ...args),
}) {
  return (
    <Toggle onToggle={onToggle}>
      {({on, togglerProps}) => (
        <div>
          <Switch on={on} {...togglerProps} />
          <hr />
          <button aria-label="custom-button" {...togglerProps}>
            {on ? 'on' : 'off'}
          </button>
        </div>
      )}
    </Toggle>
  )
}

将属性进行封装,事件的部分进行封装

增加额外获取属性方法

 getStateAndHelpers() {
    return {
      on: this.state.on,
      toggle: this.toggle,
// 增加额外的属性 用于给函数的子组件方便获取任意需要的属性
      getTogglerProps: this.getTogglerProps,
    }
  }

定义getTogglerProps方法

不仅要考虑到封装好所有的props属性,也要封装其他的需要属性,比如aria-pressed的属性,以及对特殊OnClick进行事件的绑定,与此同时也让其触发toggle原本的方法

getTogglerProps = ({onClick,className, ...props} = {}) => ({
    'aria-pressed': this.state.on,
    onClick: callAll(onClick, this.toggle),
// 如果你想添加额外的className进行支持  在其传入时 进行添加
className:`${className} our-custom-class-name`
    ...props,
  })

定义callAll 方法 执行

需要额外注意的是,前面要追加fn &,因为追加的事件是需要显性定义然后才执行的,而如果是toogle本身的点击是不需要定义点击事件的,直接执行事件会报错。

const callAll = (...fns) => (...args) =>
  fns.forEach(fn => fn && fn(...args))

使用时的外部事件以及使用差异

function Usage({
  onToggle = (...args) => console.log('onToggle', ...args),
// 额外的点击事件
  onButtonClick = () => console.log('onButtonClick'),
}) {
  return (
    <Toggle onToggle={onToggle}>
      {({on, getTogglerProps}) => (
        <div>
// on属性通过getTogglerProps 赋值
          <Switch {...getTogglerProps({on})} />
          <hr />
// 试想你会怎么写?你可能会写一个行内函数 ?如果我们直接只写自己的事件,那么toggle的切换就无法完成;但写成这样toogle内就不方便修改或者外部使用时外部与组件内触发的事件本就是不同的。
<button
          {...togglerProps}
            'aria-label': 'custom-button',
            id="custom-button-id",
            onClick: {( => {
              onButtonClick()
              togglerProps.onClick()
            })},
        >
          {on ? 'on' : 'off'}
        </button>
// 将点击事件单独作为属性传入,默认执行其默认的点击,同时将其属性一次性封装传入
          <button
            {...getTogglerProps({
              'aria-label': 'custom-button',
              onClick: onButtonClick,
              id: 'custom-button-id',
            })}
          >
            {on ? 'on' : 'off'}
          </button>
        </div>
      )}
    </Toggle>
  )
}

小结

看上去有点乱,我简单梳理下当我们的组件事件除了使用组件之外,希望方便的获取组件属性,或者需要针对一些组件事件增加额外的事件逻辑而进行一定的解耦,那么可以通过额外定义一个getToggleProps的方法来简化操作,也可以用来支持业务特殊的组件回调函数方便解耦。