Rewrite mock choice provider to hooks
This commit is contained in:
parent
ba5dac7405
commit
d58b1046ff
1 changed files with 88 additions and 80 deletions
|
@ -1,91 +1,99 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent";
|
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
|
||||||
interface ChoiceProviderProps {
|
interface ChoiceProviderProps {
|
||||||
children: (props: {
|
children: (
|
||||||
choices: SingleAutocompleteChoiceType[];
|
props: FetchMoreProps & {
|
||||||
hasMore: boolean;
|
choices: SingleAutocompleteChoiceType[];
|
||||||
loading: boolean;
|
fetchChoices: (value: string) => void;
|
||||||
fetchChoices: (value: string) => void;
|
}
|
||||||
fetchMore: () => void;
|
) => React.ReactElement;
|
||||||
}) => React.ReactElement<any>;
|
|
||||||
choices: SingleAutocompleteChoiceType[];
|
choices: SingleAutocompleteChoiceType[];
|
||||||
}
|
}
|
||||||
interface ChoiceProviderState {
|
|
||||||
choices: SingleAutocompleteChoiceType[];
|
|
||||||
filteredChoices: SingleAutocompleteChoiceType[];
|
|
||||||
first: number;
|
|
||||||
loading: boolean;
|
|
||||||
timeout: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const step = 5;
|
const step = 5;
|
||||||
|
const loadingTime = 400;
|
||||||
|
|
||||||
export class ChoiceProvider extends React.Component<
|
export interface UseMockChoiceProviderOpts extends FetchMoreProps {
|
||||||
ChoiceProviderProps,
|
fetchChoices: (value: string) => void;
|
||||||
ChoiceProviderState
|
|
||||||
> {
|
|
||||||
state = {
|
|
||||||
choices: [],
|
|
||||||
filteredChoices: [],
|
|
||||||
first: step,
|
|
||||||
loading: false,
|
|
||||||
timeout: null
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = (inputValue: string) => {
|
|
||||||
if (!!this.state.timeout) {
|
|
||||||
clearTimeout(this.state.timeout);
|
|
||||||
}
|
|
||||||
const timeout = setTimeout(() => this.fetchChoices(inputValue), 500);
|
|
||||||
this.setState({
|
|
||||||
loading: true,
|
|
||||||
timeout
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleFetchMore = () => {
|
|
||||||
if (!!this.state.timeout) {
|
|
||||||
clearTimeout(this.state.timeout);
|
|
||||||
}
|
|
||||||
const timeout = setTimeout(this.fetchMore, 500);
|
|
||||||
this.setState({
|
|
||||||
loading: true,
|
|
||||||
timeout
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchMore = () =>
|
|
||||||
this.setState(prevState => ({
|
|
||||||
filteredChoices: prevState.choices.slice(0, prevState.first + step),
|
|
||||||
first: prevState.first + step,
|
|
||||||
loading: false,
|
|
||||||
timeout: null
|
|
||||||
}));
|
|
||||||
|
|
||||||
fetchChoices = (inputValue: string) => {
|
|
||||||
const choices = this.props.choices.filter(
|
|
||||||
suggestion =>
|
|
||||||
!inputValue ||
|
|
||||||
suggestion.label.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1
|
|
||||||
);
|
|
||||||
this.setState({
|
|
||||||
choices,
|
|
||||||
filteredChoices: choices.slice(0, step),
|
|
||||||
first: step,
|
|
||||||
loading: false,
|
|
||||||
timeout: null
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return this.props.children({
|
|
||||||
choices: this.state.filteredChoices,
|
|
||||||
fetchChoices: this.handleChange,
|
|
||||||
fetchMore: this.handleFetchMore,
|
|
||||||
hasMore: this.state.choices.length > this.state.filteredChoices.length,
|
|
||||||
loading: this.state.loading
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
export type UseMockChoiceProvider = [
|
||||||
|
SingleAutocompleteChoiceType[],
|
||||||
|
UseMockChoiceProviderOpts
|
||||||
|
];
|
||||||
|
export function useMockChoiceProvider(
|
||||||
|
choices: SingleAutocompleteChoiceType[]
|
||||||
|
): UseMockChoiceProvider {
|
||||||
|
const [filteredChoices, setFilteredChoices] = React.useState(
|
||||||
|
choices.slice(0, step)
|
||||||
|
);
|
||||||
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
const [first, setFirst] = React.useState(step);
|
||||||
|
const timeout = React.useRef(null);
|
||||||
|
|
||||||
|
React.useEffect(
|
||||||
|
() => () => {
|
||||||
|
if (timeout.current) {
|
||||||
|
clearTimeout(timeout.current);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleChange = (value: string) => {
|
||||||
|
if (!!timeout.current) {
|
||||||
|
clearTimeout(timeout.current);
|
||||||
|
}
|
||||||
|
timeout.current = setTimeout(() => fetchChoices(value), loadingTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchChoices = (value: string) => {
|
||||||
|
const filteredChoices = choices.filter(
|
||||||
|
suggestion =>
|
||||||
|
!value ||
|
||||||
|
suggestion.label.toLowerCase().indexOf(value.toLowerCase()) !== -1
|
||||||
|
);
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
timeout.current = setTimeout(() => {
|
||||||
|
setFilteredChoices(filteredChoices);
|
||||||
|
setLoading(false);
|
||||||
|
setFirst(step);
|
||||||
|
}, loadingTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFetchMore = () => {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
timeout.current = setTimeout(() => {
|
||||||
|
setFilteredChoices(choices.slice(0, first + step));
|
||||||
|
setLoading(false);
|
||||||
|
setFirst(first + step);
|
||||||
|
}, loadingTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
filteredChoices,
|
||||||
|
{
|
||||||
|
fetchChoices: handleChange,
|
||||||
|
hasMore: choices.length > filteredChoices.length,
|
||||||
|
loading,
|
||||||
|
onFetchMore: handleFetchMore
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChoiceProvider: React.FC<ChoiceProviderProps> = ({
|
||||||
|
children,
|
||||||
|
choices
|
||||||
|
}) => {
|
||||||
|
const [filteredChoices, opts] = useMockChoiceProvider(choices);
|
||||||
|
|
||||||
|
return children({
|
||||||
|
choices: filteredChoices,
|
||||||
|
...opts
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue