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