Home > OS >  React with Typescript: why is my array variable an object?
React with Typescript: why is my array variable an object?

Time:03-12

I'm making a simple To-do list application to put into practice what I'm learning, and I'm doing it in Typescript. Literally half an hour ago the application was working fine, but now "all of a sudden" (surely I touched something I shouldn't have and I'm not realizing what) I can't apply .map() on my state variable where I store the user's tasks because in theory it's an object.

Code of the component where I create my state and define it as an array:

import React, { useState, useEffect } from 'react'
import InputForm from '../InputForm/InputForm'
import ItemsContainer from './ItemsContainer'

export default function Container() {
  const [userTasks, setUserTasks] = useState(
    new Array<{ id: string; name: string; completed: boolean }>()
  )

  // This function is received by <InputForm /> and it returns the new Task.
  // Updates the current tasks (userTasks state) with the new { task } received.
  const addTaskHandler = (task: any) => {
    setUserTasks(task)
  }

  useEffect(() => {
    setUserTasks(JSON.parse(window.localStorage.getItem('Task') || '{}'))
  }, [])

  useEffect(() => {
    window.localStorage.setItem('Task', JSON.stringify(userTasks))
  }, [userTasks])

  return (
    <div className="flex flex-col px-4 container mx-auto sm:max-w-screen-sm">
      {console.log(Array.isArray(userTasks(}
      <InputForm onAddTask={addTaskHandler} />
      <ItemsContainer tasks={userTasks} />
    </div>
  )
}

Code of the component where I do the .map():

import React from 'react'
import Items from '../Items/Items'

interface Props {
  tasks: Array<{
    id: string
    name: string
    completed: boolean
  }>
}

const ItemsContainer: React.FC<Props> = ({tasks}) => {
  return (
    <ul className='h-96 overflow-auto flex flex-col items-center scrollbar-hide'>
      {tasks.map((task) => (
        <Items name={task.name} key={task.id} />
      ))}
    </ul>
  )
}

export default ItemsContainer

I'm pretty sure that the main cause of this error must be sending me to use Typescript blindly and on the fly, but I would like to leave knowing the error.

Thank you very much in advance!

CodePudding user response:

This is one of the reasons you should avoid using any when using TypeScript. Type things properly, and you'll be able to see problems during compilation, not during runtime. If you use any, you're defeating the purpose of using TypeScript.

With

const addTaskHandler = (task: any) => {
    setUserTasks(task)
}

It sounds like task is a singular element of some kind - in which case calling

setUserTasks(task)

will then set the state to that single task - and not an array (which will then mean that calling .map on it will fail).

Figure out type type of a task - it looks like it might be

{ id: string; name: string; completed: boolean }

and type the argument as that, and then append that element to the array in the handler.

type Task = { id: string; name: string; completed: boolean };
const [userTasks, setUserTasks] = useState<Task[]>([]);

const addTaskHandler = (task: Task) => {
    setUserTasks([...userTasks, task]);
}
  • Related