To practice React hooks I wrote a simple todo site with ReactTS. I faced a problem that I keep receiving an error that my todos array is not iterable, despite it is defined as TodoProps[]
in State
type
Error occurs logically after 'add' button click
Error: state.todos is not iterable
If I write console.log(state.todos)
I receive undefined
I checked code on medium and it seems to be identical to mine, but anyway I cannot resolve this issue.
(Error place marked in code)
TodoProps:
export interface TodoProps {
title: string
id: number
todoKey?: number
completed: boolean
}
LayoutContext.tsx:
import { createContext, useState, ReactNode } from 'react'
export const TodoListContext = createContext<any>({})
export const TitleContext = createContext<any>({})
type LayoutContextProps = {
children: ReactNode
}
export const LayoutContext = ({ children }: LayoutContextProps): JSX.Element => {
const [title, setTitle] = useState<string>('')
const [todoList, setTodoList] = useState<object[]>([
{title: 'Todo 1', id: 418759},
{title: 'Todo 2', id: 440123}
])
return (
<TitleContext.Provider value={{ title, setTitle }}>
<TodoListContext.Provider value={{ todoList, setTodoList }}>
{children}
</TodoListContext.Provider>
</TitleContext.Provider>
)
}
Layout.tsx:
import { Button, Todos, Input } from 'Components'
import { LayoutContext } from 'Context/LayoutContext'
import cn from 'classnames'
import styles from './Layout.module.scss'
export const Layout = (): JSX.Element => {
return (
<section className={cn(styles.layout)}>
<LayoutContext>
<Todos/>
<Input/>
<Button>Add</Button>
</LayoutContext>
</section>
)
}
Button.tsx:
import styles from './Button.module.scss'
import { ButtonHTMLAttributes, DetailedHTMLProps, ReactNode, useReducer, useContext, useEffect } from 'react';
import { TodoListContext, TitleContext } from '../../Context/LayoutContext';
import { TodoProps } from 'Components/TodoComponent/Todo';
interface ButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
children: ReactNode
}
export const Button = ({ children }: ButtonProps): JSX.Element => {
const { todoList } = useContext(TodoListContext)
const { title, setTitle } = useContext(TitleContext)
type State = { todos: TodoProps[] }
type Action = { type: 'addTodo', payload: string }
const reducer = (state: State, action: Action) => {
switch (action.type) {
case 'addTodo':
const newTodoCard: TodoProps = {
title: action.payload,
id: Math.floor(Math.random() % 10),
completed: false
}
console.log(todoList)
console.log(state.todos)
return {
Error here
\/\/\/\/\/\/\/\/\/\/\/\/\/\/
todos: [...state.todos, newTodoCard]
/\/\/\/\/\/\/\/\/\/\/\/\/\/\
}
}
}
const [state, dispatch] = useReducer(reducer, todoList)
const handleAdd = (e: any) => {
e.preventDefault()
dispatch({ type: 'addTodo', payload: title})
setTitle('')
}
return (
<button
type='submit'
onClick={handleAdd}
className={styles.button}
>{children}</button>
)
}
Don't know if I can add any more information..