next.js 错误:tRPC和Mantine CSS自定义钩子上的钩子调用无效

gpnt7bae  于 2023-04-20  发布在  其他
关注(0)|答案(1)|浏览(135)

我在Next.js上有一个Unhandled Runtime Error。用void类型调用箭头函数不是问题。我在Mantine CSS库上实现useForm钩子之前做的。

Unhandled Runtime Error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

这里是代码。

import {
  Container,
  Input,
  Text,
  Flex,
  ActionIcon,
  ScrollArea,
  TextInput,
} from '@mantine/core'
import { useForm } from '@mantine/form'
import { useSession } from 'next-auth/react'
import { api } from '~/utils/api'
import { HiTrash } from 'react-icons/hi'

const TodoApp = () => {
  const form = useForm({
    initialValues: {
      title: '',
    },
  })

  const { data: sessionData } = useSession()

  const { data: tasks, refetch: refetchTasks } = api.task.getAll.useQuery(
    undefined,
    { enabled: sessionData?.user !== undefined }
  )

  const createTask = (values: { title: string }) => {
    return api.task.create
      .useMutation({ onSuccess: async () => await refetchTasks() })
      .mutate({
        title: values.title,
        recursion: {},
        analytics: {},
        reminder: {},
        taskSequence: {},
      })
  }

  const deleteTask = api.task.delete.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  return (
    <>
      <Container my={64} px={32} bg='gray.8' h='80vh' w='40rem'>
        <form
          onSubmit={form.onSubmit(values => {
            console.log(values)
            createTask(values)
          })}
        >
          <TextInput
            py={64}
            placeholder='Add Your Task Here.'
            {...form.getInputProps('title')}
          />
        </form>
        <ScrollArea h={400}>
          <Flex gap='md' justify='flex-start' direction='column'>
            {tasks?.map(task => (
              <Flex
                key={task.id}
                justify='space-between'
                bg='pink.9'
                p={8}
                sx={{ borderRadius: '0.4rem' }}
              >
                <Text fw={700} c='white'>
                  {task.title}
                </Text>
                <ActionIcon color='grape' variant='transparent'>
                  <HiTrash
                    size='1.5rem'
                    onClick={() => {
                      deleteTask.mutate({ id: task.id })
                    }}
                  />
                </ActionIcon>
              </Flex>
            ))}
          </Flex>
        </ScrollArea>
      </Container>
    </>
  )
}

export default TodoApp

我可以使用这个版本在我的数据库中添加数据。

import {
  Container,
  Input,
  Box,
  Text,
  Button,
  Flex,
  ActionIcon,
  ScrollArea,
} from '@mantine/core'
import { useSession } from 'next-auth/react'
import { api } from '~/utils/api'
import { HiTrash } from 'react-icons/hi'
import type { BaseSyntheticEvent } from 'react'

const TodoApp = () => {
  const { data: sessionData } = useSession()

  const { data: tasks, refetch: refetchTasks } = api.task.getAll.useQuery(
    undefined,
    { enabled: sessionData?.user !== undefined }
  )

  const createTask = api.task.create.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  const deleteTask = api.task.delete.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  return (
    <>
      <Container my={64} px={32} bg='gray.8' h='80vh' w='40rem'>
        <Input
          py={64}
          placeholder='Add Your Task Here.'
          onKeyDown={e => {
            if (e.currentTarget.value.length < 1) return
            if (e.key === 'Enter') {
              createTask.mutate({
                title: e.currentTarget.value,
                recursion: {},
                analytics: {},
                reminder: {},
                taskSequence: {},
              })
              e.currentTarget.value = ''
            }
          }}
        />
        <ScrollArea h={400}>
          <Flex gap='md' justify='flex-start' direction='column'>
            {tasks?.map(task => (
              <Flex
                key={task.id}
                justify='space-between'
                bg='pink.9'
                p={8}
                sx={{ borderRadius: '0.4rem' }}
              >
                <Text fw={700} c='white'>
                  {task.title}
                </Text>
                <ActionIcon color='grape' variant='transparent'>
                  <HiTrash
                    size='1.125rem'
                    onClick={() => {
                      deleteTask.mutate({ id: task.id })
                    }}
                  />
                </ActionIcon>
              </Flex>
            ))}
          </Flex>
        </ScrollArea>
      </Container>
    </>
  )
}

export default TodoApp
w9apscun

w9apscun1#

分离.useMutation和.mutate的调用方法很有帮助。我不知道为什么。

...
  const createTask = api.task.create.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  const createTaskValues = (values: { title: string }) =>
    createTask.mutate({
      title: values.title,
      recursion: {},
      analytics: {},
      reminder: {},
      taskSequence: {},
    })

  const deleteTask = api.task.delete.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  return (
    <>
      <Container my={64} px={32} bg='gray.8' h='80vh' w='40rem'>
        <form
          onSubmit={form.onSubmit(values => {
            if (form.values.title.length <= 0) return
            console.log(values)
            createTaskValues(values)
            form.values.title = ''
          })}
        >
          <TextInput
            py={64}
            placeholder='Add Your Task Here.'
            {...form.getInputProps('title')}
          />
        </form>
...

相关问题