简体   繁体   English

useEffect 无限循环

[英]infinite loop in useEffect

I'm trying to create an autoselect if it's only one element in the options.如果它只是选项中的一个元素,我正在尝试创建一个自动选择。 Unfortunately, the option data from the server is passes several times, which makes the code slow and stops working at some point.不幸的是,来自服务器的选项数据被多次传递,这使得代码变慢并在某些时候停止工作。 is there any way to use only the final value of the options without intermediate ones?有没有办法只使用选项的最终值而不使用中间值? and how it can be done以及如何做到

export const FormikSelect: FC<IFormikSelect & FieldProps> = ({
  field,
  form,
  options,
  other = [],
  placeholder,
  isFilterable,
  isMulti,
  isClearable,
  filterStyle,
}) => {
  const {t} = useTranslation()
  const {width} = useWindowSize()
  const {name, value} = field
  const {setFieldValue, errors, setFieldError} = form
  const error = get(errors, name)
  const prevOptionsRef = useRef(options)
  const [currentOptions, setCurrentOptions] = useState(() => {
    if (!isEmpty(other)) {
      if (value && other.find((o) => o.value === value.value)) {
        return [...options, ...other]
      }
      return [...options, {label: t('OTHER'), value: 'other_value_button'}]
    }
    return options
  })

  useEffect(() => {
    if (options.length === 1) {
      console.log('options:', options)
      setFieldValue(name, options[0])
      if (error) setFieldError(name, undefined)
    }
  }, [options])

i tried to use useMemo but it didn't work.我尝试使用 useMemo 但它没有用。 also i tried using [] in useEffect dependencies but that didn't work either.我也尝试在 useEffect 依赖项中使用 [] 但这也不起作用。 maybe there is some non-obvious way to solve the problem也许有一些不明显的方法来解决这个问题

I think your issue is that your options is a new array at each render.我认为您的问题是您的options在每次渲染时都是一个数组。 So you can either wrap it with useMemo before passing it to your Select , or changing the dependency array of your use effect to have only primitives所以你可以在将它传递给你的Select之前用useMemo包装它,或者将你的使用效果的依赖数组更改为只有基元

const isOnlyOneOption = options.length === 1;
const [firstOption] = options;
useEffect(() => ..., [isOnlyOneOption, firstOption])

Note that firstOption should be a primitive, not an object, otherwise you'll run into same schema.请注意, firstOption应该是原始选项,而不是对象,否则您将遇到相同的模式。 So maybe you'll need only to pass firstOption.value to your useEffect所以也许你只需要将firstOption.value传递给你的useEffect

You can also use the useRef hook to store the previous value of options and compare it to the current value in the effect.您还可以使用 useRef 挂钩存储选项的先前值并将其与效果中的当前值进行比较。 If the values are the same, you can skip the update.如果值相同,则可以跳过更新。 Here's an example of how you can do this:以下是如何执行此操作的示例:

const prevOptionsRef = useRef(options)

useEffect(() => {
  if (prevOptionsRef.current !== options) {
    prevOptionsRef.current = options
    if (options.length === 1) {
      console.log('options:', options)
      setFieldValue(name, options[0])
      if (error) setFieldError(name, undefined)
    }
  }
}, [options])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM