为什么调用 useQuery 函数时 "Invalid hook call"?

Why when useQuery function is called "Invalid hook call"?

我正在尝试在自定义组件中调用 react-admin 固有的 useQuery() 函数,出现上述错误。我完全糊涂了,我不知道该怎么做。错误很明显,我只是不知道如何解决它。我尝试访问错误消息中的网站并按照说明进行操作,但我仍然无法成功。

import React, { Component } from 'react';
import FolkMe from './Folkme';
import Settings from './Settings';
import Times from './Times';
import Controller from './Controller';
import axios from "axios";
import './App.css';
import { useQuery, Loading, Error } from 'react-admin';




export default class App extends Component {
  constructor(props) {
    super(props);

    this.audioBeep = React.createRef();

    this.state = {
      breakLength: Number.parseInt(this.props.defaultBreakLength, 10),
      sessionLength: Number.parseInt(this.props.defaultSessionLength, 10),
      timeLabel: 'Session',
      timeLeftInSecond: Number.parseInt(this.props.defaultSessionLength, 10) * 60,
      isStart: false,
      timerInterval: null
    }

    this.onIncreaseBreak = this.onIncreaseBreak.bind(this);
    this.onDecreaseBreak = this.onDecreaseBreak.bind(this);
    this.onIncreaseSession = this.onIncreaseSession.bind(this);
    this.onDecreaseSession = this.onDecreaseSession.bind(this);
    this.onReset = this.onReset.bind(this);
    this.onStartStop = this.onStartStop.bind(this);
    this.decreaseTimer = this.decreaseTimer.bind(this);
    this.phaseControl = this.phaseControl.bind(this);
    this.loadData = this.loadData.bind(this);
    this.submitTime = this.submitTime.bind(this);
  }

  onIncreaseBreak() {
    if (this.state.breakLength < 60 && !this.state.isStart) {
      this.setState({
        breakLength: this.state.breakLength + 1
      });
    }
  }

  onDecreaseBreak() {
    if (this.state.breakLength > 1 && !this.state.isStart) {
      this.setState({
        breakLength: this.state.breakLength - 1
      });
    }
  }

  onIncreaseSession() {
    if (this.state.sessionLength < 60 && !this.state.isStart) {
      this.setState({
        sessionLength: this.state.sessionLength + 1,
        timeLeftInSecond: (this.state.sessionLength + 1) * 60
      });
    }
  }

  onDecreaseSession() {
    if (this.state.sessionLength > 1 && !this.state.isStart) {
      this.setState({
        sessionLength: this.state.sessionLength - 1,
        timeLeftInSecond: (this.state.sessionLength - 1) * 60
      });
    }
  }

  onReset() {
    this.setState({
      breakLength: Number.parseInt(this.props.defaultBreakLength, 10),
      sessionLength: Number.parseInt(this.props.defaultSessionLength, 10),
      timeLabel: 'Session',
      timeLeftInSecond: Number.parseInt(this.props.defaultSessionLength, 10) * 60,
      isStart: false,
      timerInterval: null
    });

    this.audioBeep.current.pause();
    this.audioBeep.current.currentTime = 0;
    this.state.timerInterval && clearInterval(this.state.timerInterval);
  }



  loadData(profileId){ 
    // console.log(this.props);
  const { data, loading, error } = useQuery({ 
    type: 'getOne',
    resource: 'profiles',
    payload: { id: 1 }
});

console.log(data);
  }

  submitTime() {
    let timeDoneSoFar = (this.state.sessionLength * 60) - this.state.timeLeftInSecond;

  }

  onStartStop() {
    this.submitTime();

    if (!this.state.isStart) {
      this.setState({
        isStart: !this.state.isStart,
        timerInterval: setInterval(() => {
          this.decreaseTimer();
          this.phaseControl();
        }, 1000)
      })
    } else {
      this.audioBeep.current.pause();
      this.audioBeep.current.currentTime = 0;
      this.state.timerInterval && clearInterval(this.state.timerInterval);

      this.setState({
        isStart: !this.state.isStart,
        timerInterval: null
      });
    }
  }

  decreaseTimer() {
    this.setState({
      timeLeftInSecond: this.state.timeLeftInSecond - 1
    });
  }

  phaseControl() {
    if (this.state.timeLeftInSecond === 0) {
      this.audioBeep.current.play();
    } else if (this.state.timeLeftInSecond === -1) {
      if (this.state.timeLabel === 'Session') {
        this.setState({
          timeLabel: 'Break',
          timeLeftInSecond: this.state.breakLength * 60
        });
      } else {
        this.setState({
          timeLabel: 'Session',
          timeLeftInSecond: this.state.sessionLength * 60
        });
      }
    }
  }

  render() {
    this.loadData(this.props.profileId);
    return (
      <div className="pomodoro-clock">

        <Settings
          breakLength={this.state.breakLength}
          sessionLength={this.state.sessionLength}
          isStart={this.state.isStart}
          onDecreaseBreak={this.onDecreaseBreak}
          onDecreaseSession={this.onDecreaseSession}
          onIncreaseBreak={this.onIncreaseBreak}
          onIncreaseSession={this.onIncreaseSession}
        />

        <Times
          timeLabel={this.state.timeLabel}
          timeLeftInSecond={this.state.timeLeftInSecond}
        />

        <Controller
          onReset={this.onReset}
          onStartStop={this.onStartStop}
          isStart={this.state.isStart}
        />

        <audio id="beep" preload="auto" src="..." ref={this.audioBeep}></audio>
      </div>
    );
  }
}

这是错误信息

×
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 .... for tips about how to debug and fix this problem.
▶ 4 stack frames were collapsed.
App.loadData
src/src/components/pomodoro/App.js:91
  88 | 
  89 | loadData(profileId){ 
  90 |   // console.log(this.props);
> 91 |  useQuery({ 
     | ^  92 |   type: 'getOne',
  93 |   resource: 'profiles',
  94 |   payload: { id: profileId }

useQuery 旨在用于功能组件而不是 class 组件内的功能,这就是您收到该错误的原因。对于 class 组件,您需要使用 Query 组件。

检查 react-admin 查询 API 部分中的 legacy component doc

import { Query, Loading, Error } from 'react-admin';
...
render() {
    return <Query type='getOne' resource='profiles' payload={{ id: this.props. profileId }}>
        {({ data, loading, error }) => {
            if (loading) { return <Loading />; }
            if (error) { return <Error />; }
            return (
              <div className="pomodoro-clock">
                <Settings
                  breakLength={this.state.breakLength}
                  sessionLength={this.state.sessionLength}
                  isStart={this.state.isStart}
                  onDecreaseBreak={this.onDecreaseBreak}
                  onDecreaseSession={this.onDecreaseSession}
                  onIncreaseBreak={this.onIncreaseBreak}
                  onIncreaseSession={this.onIncreaseSession}
                />

                <Times
                  timeLabel={this.state.timeLabel}
                  timeLeftInSecond={this.state.timeLeftInSecond}
                />

                <Controller
                  onReset={this.onReset}
                  onStartStop={this.onStartStop}
                  isStart={this.state.isStart}
                />

                <audio id="beep" preload="auto" src="..." ref={this.audioBeep}></audio>
              </div>
            )
        }}
    </Query>
}