React與hook的二三事

本來新出的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的有點理解還不深吧,對比後感覺也就就是語法糖不一樣而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章