Ошибка типа: недопустимая попытка распространить не итерируемый экземпляр с эффектом использования

#reactjs #use-effect

#reactjs #use-effect

Вопрос:

Не уверен, почему, но я получаю это сообщение об ошибке:

 TypeError: Invalid attempt to spread non-iterable instance
 

Есть ли способ сопоставить данные, чтобы иметь возможность сохранять useEffect их до useEffect запуска?

Похоже, что эта карта не работает.

   const projectId = scheduleData amp;amp; scheduleData.map(item => item.project_id).map(x => ({label: x, value: x}))
const schedules = () => {


  const loading = useContext(LoadingContext)
  const snackbar = useContext(SnackbarContext)
  const user = useContext(UserContext)


  const [scheduleData ,setScheduleData] = useState(null)
  const [usageMode, setUsageMode] = useState(false)

  const [scheduleFieldData, setScheduleFieldData] = useState({})

  const [projectsAutoComplete, setProjectsAutoComplete] = useState([])
  const [domainsAutoComplete, setDomainsAutoComplete] = useState([])

  console.log(projectId, 'projectId');

  console.log(projectsAutoComplete)

  const projectId = scheduleData amp;amp; scheduleData.map(item => item.project_id).map(x => ({label: x, value: x}))

useEffect(() => {
  setProjectsAutoComplete([...projectId])
}, [])
  console.log(projectsAutoComplete);

  useEffect(() => {
    async function onLoadScheduleData(){
      loading.setLoading(true)
      const results = await get('get_testing_schedules', user.user)
      setScheduleData(results.data)
      loading.setLoading(false)
    }
    onLoadScheduleData()
  },[])

  const onClick = () => {
    setUsageMode(!usageMode)
  }

  console.log(usageMode);

  const onScheduleFieldUpdate = (e, valueFromAutoComplete, nameFromAutoComplete) => {

    const name = nameFromAutoComplete ? nameFromAutoComplete
    : e.target.name || e.target.getAttribute('name')
    const value = valueFromAutoComplete ? valueFromAutoComplete.map(val => val.value).join(',')
      : e.target.innerText ? e.target.innerText
      : e.target.value

      setScheduleFieldData({...scheduleFieldData, ...{[name]: value}})
  }

  const onDomainAutoCompleteFieldUpdate = (e) => {
    const value = e.target.innerText.toLowerCase()
    const projectIdFiltered = projectId.filter(id => id.label.toLowerCase().startsWith(value))
    setProjectsAutoComplete(projectIdFiltered)
  }
  console.log(scheduleFieldData);

  return (
    <div className=' CriticalObjectsGrid'>
 
       <React.Fragment>
          {configs.map((config, k) => {
            const Field = config.field
            return (
              <div key={k} className='Main' style={{textAlign: 'center'}} >
                <Field  
                  uniqueIdentifier={k} 
                  name={config.name} 
                  onChange={onScheduleFieldUpdate}
                  onSelect={onScheduleFieldUpdate}
                  onAutoCompleteOnChange={onDomainAutoCompleteFieldUpdate}
                  value={scheduleFieldData[config.name]}
                  initialValues={
                  scheduleFieldData[config.name]}
                  options={projectsAutoComplete}
                />
              </div>
            )
          })}
        </React.Fragment>
      }
    </div>
  )
}

export default schedules
 

Обновленный код

 const schedules = () => {


  const loading = useContext(LoadingContext)
  const snackbar = useContext(SnackbarContext)
  const user = useContext(UserContext)
  const autoComplete = useContext(AutoCompleteContext)



  const [scheduleData ,setScheduleData] = useState(null)
  const [usageMode, setUsageMode] = useState(false)

  const [scheduleFieldData, setScheduleFieldData] = useState({})

  const [projectsAutoComplete, setProjectsAutoComplete] = useState([])




  // const projectId = scheduleData amp;amp; scheduleData.map(item => item.project_id).map(x => ({label: x, value: x}))



  const [ScheduleAutoComplete, setScheduleAutoComplete] = useState([])


  const intervals = ['"Daily"', '"Weekly"']

  const projectId = scheduleData amp;amp; scheduleData.map(item => item.project_id).map(x => ({label: x, value: x}))

useEffect(() => {
  // setProjectsAutoComplete([...projectId])

  setScheduleAutoComplete([...intervals])




}, [])

console.log(projectsAutoComplete);




  useEffect(() => {
    async function onLoadScheduleData(){
      loading.setLoading(true)
      const results = await get('get_testing_schedules', user.user)
      setScheduleData(results.data)

      if (projectId){setProjectsAutoComplete([...projectId])
      }
      loading.setLoading(false)
    }
    onLoadScheduleData()
  },[])

  const onClick = () => {
    setUsageMode(!usageMode)
  }

  console.log(projectsAutoComplete);



  const onScheduleFieldUpdate = (e, valueFromAutoComplete, nameFromAutoComplete) => {

    const name = nameFromAutoComplete ? nameFromAutoComplete
    : e.target.name || e.target.getAttribute('name')
    const value = valueFromAutoComplete ? valueFromAutoComplete.map(val => val.value).join(',')
      : e.target.innerText ? e.target.innerText
      : e.target.value

      setScheduleFieldData({...scheduleFieldData, ...{[name]: value}})


  }

  const onDomainAutoCompleteFieldUpdate = () => { 
    setScheduleAutoComplete(intervals)
    setProjectsAutoComplete(projectId)



  }

  console.log(projectsAutoComplete);



  return (
    <div className=' CriticalObjectsGrid'>
      {usageMode === false ? 
        <React.Fragment>
          <Button
          text='Creat schedule'
          onClick={onClick}
          />
        </React.Fragment>

        :

        <React.Fragment>
          {configs.map((config, k) => {
            const Field = config.field
            return (
              <div key={k} className='Main' style={{textAlign: 'center'}} >
                <Field  
                  uniqueIdentifier={k} 
                  name={config.name} 
                  onChange={onScheduleFieldUpdate}
                  onSelect={onScheduleFieldUpdate}
                  onAutoCompleteOnChange={onDomainAutoCompleteFieldUpdate}
                  value={scheduleFieldData[config.name]}
                  initialValues={scheduleFieldData[config.name]}
                  options={config.name === 'interval' ? ScheduleAutoComplete : config.name === 'project' ? ['projectsAutoComplete'] : []  }

                />
              </div>
            )
          })}


        </React.Fragment>
      }


    </div>
  )
}

export default schedules
 

Комментарии:

1. можете ли вы распечатать scheduleData? […ProjectID]: ProjectID, похоже, не является массивом (не итерируемым)

2. Да, конечно, он возвращает мне массив [70,71], который я обновил в своем коде

3. Похоже, когда я нажимаю на эффект использования, он не хочет его использовать

4. Попробуйте const projectId = scheduleData ? scheduleData.map(item => item.project_id).map(x => ({label: x, value: x})) : [] , это всегда должен быть массив, даже если нет scheduleData

5. Привет, спасибо, но когда я регистрирую projectsAutocomplete, он возвращает пустой массив.

Ответ №1:

Эта ошибка относится к вашей попытке распространения projectId в вашем первом useEffect перехвате. Во время выполнения projectId имеет значение null, поскольку он получает это значение из следующей строки, где scheduleData имеет начальное значение null.

 const projectId = scheduleData amp;amp; scheduleData.map(item => item.project_id).map(x => ({label: x, value: x}))
 

Чтобы избежать этой ошибки, вы могли бы просто выполнить setProjectsAutoComplete([...projectId]) if (projectId) проверку, например:

 useEffect(() => {
   if (projectId){
      setProjectsAutoComplete([...projectId])
   }
}, [])
 

но лучшим решением было бы объединить ваши два useEffect перехвата, чтобы setProjectsAutoComplete([...projectId]) он выполнялся после onLoadScheduleData()

Редактировать:

Попробуйте это:

     const [projectId, setProjectId] = useState([])

    const intervals = ['"Daily"', '"Weekly"']

    async function onLoadScheduleData(){
        loading.setLoading(true)
        const results = await get('get_testing_schedules', user.user)
        if (results.data) {
            id = results.data.map(item => item.project_id).map(x => ({label: x, value: x}))
            setProjectId(id)
            setProjectsAutoComplete([...id])
        }
        loading.setLoading(false)
    }

    useEffect(() => {
        setScheduleAutoComplete([...intervals])
        onLoadScheduleData()
    },[])

    const onClick = () => {
        setUsageMode(!usageMode)
    }
 

Я scheduleData полностью удалил переменную, поскольку не похоже, что ее нужно сохранять в состоянии. Вместо этого я создал projectId переменную с отслеживанием состояния, поскольку она, похоже, используется в других местах. Я переместил определение onScheduleLoadData функции за пределы крючка useEffect и переместил projectId логику внутри него. Я также объединил оба перехватчика useEffect, потому что они имели одинаковые зависимости. Дайте мне знать, если это больше того, что вы искали.

Комментарии:

1. спасибо, но я получаю возвращенный пустой массив, есть идеи? Я обновлю код

2. Я отредактирую свое решение с помощью нового кода для вас