React Select组件封装

React Select组件封装,第1张

React Select组件封装

import React, { useContext, useEffect, useRef, useState } from 'react'
//判断受控与非受控组件的钩子
import { useAutoControlledState } from './useAutoControlledState'

//使用context可以支持各种嵌套
const SelectContext = React.createContext()

function Option({ value, children, ...rest }) {
  const context = useContext(SelectContext)
  if (context === undefined)
    throw new Error('Select.Option must be used within Select')

  const { state, setState, finalOptions, setFinalOptions } = context

  //useEffect是异步的
  useEffect(() => {
    setFinalOptions((prev) =>
      //先筛选掉再进行拼接 避免重复
      prev.filter((item) => item.value !== value).concat({ value, children })
    )
		//由于依赖发生改变的话也会触发useEffect 所以要在他每次return的时候筛选一遍 return 是每一次都会触发的
    return ()	 =>
      setFinalOptions((prev) => prev.filter((item) => item.value !== value))
  }, [value, children, setFinalOptions])
	//	添加选中高亮
  const isActive = value === state

  return (
     {
        if (el) {
          //添加选中的高亮
          if (isActive) {
            el.dataset.isActive = isActive
          } else {
            delete el.dataset.isActive
          }
        }
      }}
      onClick={() => setState(value)}
      {...rest}
    >
      {children}
    
  )
}

export function Select({
  options = [],
  value,
  defaultValue,
  onChange,
  //可以对options的key做一个映射
  optionsMapping,
  children,
  ...rest
}) {
  const [state, setState] = useAutoControlledState({
    value,
    defaultValue,
    onChange,
  })
	//options可以是简单值[‘’,‘’,‘’],也可以是对象形式的
  const mappedOptions = optionsMapping
    ? options.map(optionsMapping)
    : options.map((item) => ({
        value: typeof item === 'object' ? item.value : item,
        children: typeof item === 'object' ? item.children : item,
      }))
	// 给子组件传入一个引用 然后由子组件去修改这个引用将options传到父组件来 
  //一开始用的是useRef 但是useRef去改变这个引用是不会触发更新的 会导致第一次取不到值 所以改成了useState
  const [finalOptions, setFinalOptions] = useState(mappedOptions)

  //当前选中的值
  const selected = finalOptions.find((item) => item.value === state)

  return (
    {
        state,
        setState,
        finalOptions,
        setFinalOptions,
      }}
    >
      
{selected?.children} {mappedOptions.map((item) => ( ))} {children}
) } Select.Option = Option

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1321059.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-11
下一篇 2022-06-11

发表评论

登录后才能评论

评论列表(0条)

保存