#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})) : []
, это всегда должен быть массив, даже если нет scheduleData5. Привет, спасибо, но когда я регистрирую 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. Я отредактирую свое решение с помощью нового кода для вас