Home > Net >  onClick type in React
onClick type in React

Time:08-17

Hi I am trying to make a basic todo list app in React using Typescript and I struggle with filter logic. There are three filter values 'All', 'Active' and 'Completed' which should be stored in the filter variable using useState. But I got following error:

Argument of type 'MouseEvent<HTMLInputElement, MouseEvent>' is not assignable to parameter of type '"All" | "Active" | "Completed" | ((val: "All" | "Active" | "Completed") => "All" | "Active" | "Completed")'

Problematic is onClick event with setFilter() function. I tried to set onClick's type to (e: React.MouseEvent<HTMLInputElement>), but it didn't work.

Form.tsx:

type Task = {
  id: string
  name: string
  completed: boolean
}

const filterMap = {
  All: () => true,
  Active: (task: Task) => !task.completed,
  Completed: (task: Task) => task.completed,
}

const filterOptions = Object.keys(filterMap)

export const Form = () => {
  const [name, setName] = useState('')
  const [tasks, setTasks] = useLocalStorage('tasks:list', [] as Task[])
  const [filter, setFilter] = useLocalStorage<keyof typeof filterMap>('task:filter', 'All')

  const itemsLeft = tasks.filter(task => task.completed === false).length

  const handleDelete = (id: string) => setTasks(tasks.filter(task => task.id !== id))

  const handleDeleteChecked = () => setTasks(tasks.filter(task => task.completed === false))

  const handleCheck = (id: string) =>
    setTasks(tasks.map(task => (task.id === id ? { ...task, completed: !task.completed } : task)))

  const checkIfSelected = tasks.find(task => task.completed)

  return (
    <form
      onSubmit={e => {
        e.preventDefault()
        const newTask = {
          id: generateId(),
          name,
          completed: false,
        }
        setTasks([...tasks, newTask])
        setName('')
      }}
    >
      <input
        css={s.input}
        type='text'
        placeholder='What needs to be done?'
        autoFocus={true}
        required={true}
        maxLength={t.taskMaxLength}
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <hr css={s.divider} />
      {tasks.filter(filterMap[filter]).map(task => (
        <div key={task.id}>
          <div css={s.taskContainer}>
            <Checkbox
              checked={task.completed}
              onChange={() => {
                handleCheck(task.id)
              }}
            />
            {task.completed ? <p css={s.strikethrough}>{task.name}</p> : <p>{task.name}</p>}
            <button css={s.deleteTask} type='button' onClick={() => handleDelete(task.id)}>
               
            </button>
          </div>
          <hr css={s.divider} />
        </div>
      ))}
      <div css={s.footer}>
        <div>{itemsLeft !== 1 ? `${itemsLeft} items left` : '1 item left'}</div>
        <div css={s.filterBtnWrapper}>
          {filterOptions.map(option => (
            <input
              key={option}
              value={option}
              type='button'
              onClick={option => {
                setFilter(option)  // ERROR HERE
              }}
              css={[
                s.clearCompleted,
                s.filterBtn,
                filter === option ? s.filterBtnSelected : undefined,
              ]}
            />
          ))}
        </div>
        {checkIfSelected ? (
          <button type='button' css={s.clearCompleted} onClick={handleDeleteChecked}>
            Clear completed
          </button>
        ) : null}
      </div>
    </form>
  )
}

CodePudding user response:

You have to set:

e: React.ChangeEvent<HTMLInputElement>

not

e: React.ChangeEvent

CodePudding user response:

Few changes in your code should do the trick:

filterOptions are string[], so casted them to this.

const filterOptions = Object.keys(filterMap) as (keyof typeof filterMap)[];

Next: your option as a first param is overriding option from map to MouseEvent... instead of what it was before, so

onClick={() => {
  setFilter(option); // ERROR WAS HERE PREVIOUSLY
}}

Sorry, i cant completely reproduce your code but for me - no errors shown from tsc.

  • Related