Ошибка получения ** Ошибка: неверный вызов ловушки. Хуки могут быть вызваны только внутри тела компонента функции. ** - PullRequest
0 голосов
/ 24 апреля 2020

Я использую пользовательский интерфейс материала, и когда я хочу использовать приведенный ниже код (Компонент) в моем приложении reactjs без кода ниже, мое приложение работает нормально, но когда я использую код ниже, тогда я получаю Ошибка: Неверный вызов ловушки. Хуки могут быть вызваны только внутри тела компонента функции. . Я использую Typescript для reactjs. и я хочу использовать реагирующий материал-пользовательский интерфейс

Я хочу использовать этот код (компонент)

const [checked, setChecked] = React.useState(true);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };
<div>
      <Checkbox
        checked={checked}
        onChange={handleChange}
        inputProps={{ 'aria-label': 'primary checkbox' }}
      />
</div>

Здесь я хочу использовать

import React, { Component } from 'react'
import ApiService from "../../service/ApiService";
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Button from '@material-ui/core/Button';
import CreateIcon from '@material-ui/icons/Create';
import DeleteIcon from '@material-ui/icons/Delete';
import Typography from '@material-ui/core/Typography';
import { Grid } from '@material-ui/core';
import Checkbox from '@material-ui/core/Checkbox';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';

class CategoryListUserComponent extends Component<any,any>{

    constructor(props: any){
        super(props)
        this.state = {
            users: [],
            message: null,
            checked: true
        }
        this.deleteUser = this.deleteUser.bind(this);
        this.editUser = this.editUser.bind(this);
        this.addUser = this.addUser.bind(this);
        this.reloadUserList = this.reloadUserList.bind(this);
    }

    componentDidMount() {
        this.reloadUserList();
    }

    reloadUserList() {
        ApiService.fetchUsers()
            .then((res) => {
                this.setState({users: res.data})
            });
    }

    deleteUser(userId: any) {
        ApiService.deleteUser(userId)
           .then(res => {
               this.setState({message : 'User deleted successfully.'});
               this.setState({users: this.state.users.filter((user: { id: any; }) => user.id !== userId)});
           })
    }

    editUser(id: any) {
        window.localStorage.setItem("userId", id);
        this.props.history.push('/edit-user');
    }

    addUser() {
        window.localStorage.removeItem("userId");
        this.props.history.push('/add-user');
    }

    render() {
        return (
            <Grid>
                 <Typography variant="h4" align="left" style={style}>Category List</Typography>
                <Button variant="contained" color="primary" onClick={() => this.addUser()}>
                    Add Category
                </Button>
                <Grid  container   className="listContainer">
                <Table>
                    <TableHead>
                        <TableRow>
                            <TableCell>Id</TableCell>
                            <TableCell>Initiator</TableCell>
                            <TableCell align="left">Category</TableCell>
                            <TableCell align="left">Date</TableCell>
                            <TableCell align="left">Time</TableCell>
                            <TableCell align="left">Status</TableCell>
                            <TableCell align="left"></TableCell>
                            <TableCell align="left"></TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {this.state.users && this.state.users.map((row: { id: {} | null | undefined; name: React.ReactNode; email: React.ReactNode; username: React.ReactNode; age: React.ReactNode; salary: React.ReactNode; }) => (
                            <TableRow>
                                <TableCell scope="row">
                                    {row.id}
                                </TableCell>
                                <TableCell align="left">{row.name}</TableCell>
                                <TableCell align="left">{row.username}</TableCell>
                                <TableCell align="left">13-10-2020</TableCell>
                                <TableCell align="left">10:00 AM</TableCell>
                                <TableCell align="left"><FormControl component="fieldset">
                                <FormGroup aria-label="position" row>
                                    <FormControlLabel
                                    value="top"
                                    control={<Checkbox color="primary" checked />}
                                    label=""
                                    labelPlacement="start"
                                    />

                                </FormGroup>
                                <FormGroup>
                                <Checkbox

  onChange={(event) => {
    this.setState({
      checked: event.target.checked,
    )}
  }}
  inputProps={{ 'aria-label': 'primary checkbox' }}
/>

                                </FormGroup>
                                </FormControl>
                                 </TableCell>
                                <TableCell align="left" onClick={() => this.editUser(row.id)}><CreateIcon /></TableCell>
                                <TableCell align="left" onClick={() => this.deleteUser(row.id)}><DeleteIcon /></TableCell>

                            </TableRow>
                        ))}
                    </TableBody>
                </Table>

            </Grid>
            </Grid>
        );
    }

}

const style ={
    display: 'flex',
    justifyContent: 'center'
}

export default CategoryListUserComponent;

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Ошибка не требует пояснений, так как она говорит Хуки могут вызываться только внутри тела компонента функции .

CategoryListUserComponent в настоящее время является компонентом на основе класса React.useState является ловушкой и может использоваться только в функциональном компоненте.

Существует три способа решения этой проблемы:

  1. Преобразование компонента CategoryListUserComponent в функциональный компонент (рекомендуется) .
  2. Вместо того, чтобы включать код (содержащий флажок) в CategoryListUserComponent, включите его в качестве компонента в родительский компонент.
  3. Преобразуйте приведенный выше код в компонент на основе классов.

Как уже упоминалось @wentjun Вы можете преобразовать приведенный выше код в компонент на основе классов

Вместо использования ловушки определите ваше состояние проверки в конструкторе, например

this.state = {
  users: [],
  message: null,
  checked: true, // or false
} 

И конвертируйте ваш JSX в:

<Checkbox
  checked={checked}
  onChange={(event) => {
    this.setState({
      checked: event.target.checked,
    )}
  }}
  inputProps={{ 'aria-label': 'primary checkbox' }}
/>
0 голосов
/ 24 апреля 2020

Как указано в официальной документации для крючков React, крючки (например, useState) могут использоваться только в функциональных компонентах.

CategoryListUserComponent является компонентом класса.

Если вы хотите sh использовать хук useState, вам следует CategoryListUserComponent для функционального компонента.

В качестве альтернативы, Вы можете просто добавить состояние checked к CategoryListUserComponent, так что оно является частью состояния компонента.

this.state = {
  users: [],
  message: null,
  checked: true, // or false
}

И затем вы можете просто обновить состояние, используя this.setState(), когда Checkbox компонент нажат.

<Checkbox
  checked={checked}
  onChange={(event) => {
    this.setState({
      checked: event.target.checked,
    )}
  }}
  inputProps={{ 'aria-label': 'primary checkbox' }}
/>

Кроме того, я заметил, что вы определили как свои реквизиты, так и состояние как any. Это не рекомендуется, так как вы не сможете воспользоваться возможностями проверки типов в TypeScript.

Например, именно так вы можете определить свой интерфейс.

interface ListState {
  users: Something[],
  message: string | null,
  checked: boolean,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...