React与hook的二三事

本文探讨了在React项目中遇到的Invalid hook call错误,详细记录了从使用Hooks到传统类组件的转换过程,旨在帮助开发者理解并解决类似问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本来新出的hook应该是个好用的东西,但是我在组件中使用没有任何问题,项目去引用这组件时却报了个:

Invalid hook call. Hooks can only be called inside of the body of a function component.

首先判定是不是版本问题,把组件和项目都重安了一遍react的包,而且都是同一个版本,还报这个错……

算了,不浪费时间找问题了,干脆花了点时间把组件里用useState的地方换回原来的写法得了。

于是:

import React, { useState } from 'react'

import { Button, Divider, InputGroup } from '@blueprintjs/core';
import { DateInput } from "@blueprintjs/datetime";
import '@blueprintjs/datetime/lib/css/blueprint-datetime.css';
import subMonths from 'date-fns/sub_months';
import { handleFormat, localeUtils } from '../utils/localeFn';

export interface IProps { 
  isSearching: boolean;
  handleSearch: (text: string, startTime: string, endTime: string) => void;
}

export function CommonSearchPane(props: any) {
  const [ text, setText ] = useState('');
  const [ startTime, setStartTime ] = useState(handleFormat(subMonths(new Date(), 2)));
  const [ endTime, setEndTime ] = useState(handleFormat(new Date()));
  // const [ isSearch, setIsSearch ] = useState(false);
  // 人员姓名输入
  function handleInputChange(evt: React.ChangeEvent<HTMLInputElement>) {
    const target = evt.target;
    const value = target.value;
    setText(value);
  }

  function handleParse(str: string) {
      return new Date(str);
  }

  // 改变开始时间
  function handleStartChange(selectedDate: Date) {
    if (selectedDate !== null) {
      setStartTime(handleFormat(selectedDate));
    } else {
      setStartTime(handleFormat(new Date()))
    }
  }

  // 改结束始时间
  function handleEndChange(selectedDate: Date) {
    if (selectedDate !== null) {
      setEndTime(handleFormat(selectedDate));
    } else {
      setEndTime(handleFormat(new Date()));
    }
  }

  return (
    <div className='common-search-div'>
      <div className='line'>
        <div className='title'>人员姓名:</div>
        <div className='input'>
          <InputGroup placeholder='输入姓名' value={text} onChange={handleInputChange} />
        </div>
      </div>
      <div className='line'>
        <div className='title'>开始时间:</div>
        <div className='input'>
          <DateInput
            formatDate={handleFormat}
            parseDate={handleParse}
            timePrecision="second"
            showActionsBar={true}
            clearButtonText='取消'
            todayButtonText='今天'
            popoverProps={{position: 'right'}}
            dayPickerProps={{ locale: 'zh', localeUtils }}
            onChange={handleStartChange}
            value={handleParse(startTime)}
          />
        </div>
      </div>
      <div className='line'>
        <div className='title'>结束时间:</div>
        <div className='input'>
          <DateInput
            formatDate={handleFormat}
            parseDate={handleParse}
            timePrecision="second"
            showActionsBar={true}
            clearButtonText='取消'
            todayButtonText='今天'
            popoverProps={{position: 'right'}}
            dayPickerProps={{ locale: 'zh', localeUtils }}
            onChange={handleEndChange}
            value={handleParse(endTime)}
          />
        </div>
      </div>
      <div className='botton'>
        <Button loading={props.isSearching ? true : false} fill={true} text='查询' intent='primary' onClick={props.handleSearch(text, startTime, endTime)} />
      </div>
      <Divider />
    </div>
  );
}

改成了:

import React from 'react'

import { Button, Divider, InputGroup } from '@blueprintjs/core';
import { DateInput } from "@blueprintjs/datetime";
import '@blueprintjs/datetime/lib/css/blueprint-datetime.css';
import subMonths from 'date-fns/sub_months';
import { handleFormat, localeUtils } from '../utils/localeFn';

export interface IProps { 
  isSearching: boolean;
  handleSearch: (text: string, startTime: string, endTime: string) => void;
}

export interface IState { 
  text: string;
  startTime: string;
  endTime: string;
}

export class CommonSearchPane extends React.PureComponent<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      endTime: handleFormat(new Date()),
      startTime: handleFormat(subMonths(new Date(), 2)),
      text: '',
    };
  }

  public render(){
    const { text, startTime, endTime } = this.state;
    const { isSearching } = this.props;
    return (
      <div className='common-search-div'>
        <div className='line'>
          <div className='title'>人员姓名:</div>
          <div className='input'>
            <InputGroup placeholder='输入姓名' value={text} onChange={this.handleInputChange} />
          </div>
        </div>
        <div className='line'>
          <div className='title'>开始时间:</div>
          <div className='input'>
            <DateInput
              formatDate={handleFormat}
              parseDate={this.handleParse}
              timePrecision="second"
              showActionsBar={true}
              clearButtonText='取消'
              todayButtonText='今天'
              popoverProps={{position: 'right'}}
              dayPickerProps={{ locale: 'zh', localeUtils }}
              onChange={this.handleStartChange}
              value={this.handleParse(startTime)}
            />
          </div>
        </div>
        <div className='line'>
          <div className='title'>结束时间:</div>
          <div className='input'>
            <DateInput
              formatDate={handleFormat}
              parseDate={this.handleParse}
              timePrecision="second"
              showActionsBar={true}
              clearButtonText='取消'
              todayButtonText='今天'
              popoverProps={{position: 'right'}}
              dayPickerProps={{ locale: 'zh', localeUtils }}
              onChange={this.handleEndChange}
              value={this.handleParse(endTime)}
            />
          </div>
        </div>
        <div className='botton'>
          <Button loading={isSearching ? true : false} fill={true} text='查询' intent='primary' onClick={this.handleSearch(text, startTime, endTime)} />
        </div>
        <Divider />
      </div>
    );
  }

  // 搜索
  private handleSearch = (text: string, startTime: string, endTime: string) => {
    return () => {
      this.props.handleSearch(text, startTime, endTime);
    }
  }
  
  // 人员姓名输入
  private handleInputChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
    const target = evt.target;
    const value = target.value;
    this.setState({text: value});
  }

  private handleParse = (str: string) => {
      return new Date(str);
  }

  // 改变开始时间
  private handleStartChange = (selectedDate: Date) => {
    if (selectedDate !== null) {
      this.setState({startTime: handleFormat(selectedDate)});
    } else {
      this.setState({startTime: handleFormat(new Date())});
    }
  }

  // 改结束始时间
  private handleEndChange = (selectedDate: Date) => {
    if (selectedDate !== null) {
      this.setState({endTime: handleFormat(selectedDate)});
    } else {
      this.setState({endTime: handleFormat(new Date())});
    }
  }

}

或许我对hook的有点理解还不深吧,对比后感觉也就就是语法糖不一样而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值