Rewrite mock choice provider to hooks

This commit is contained in:
dominik-zeglen 2019-12-17 14:38:13 +01:00
parent ba5dac7405
commit d58b1046ff

View file

@ -1,91 +1,99 @@
import React from "react";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent";
import { FetchMoreProps } from "@saleor/types";
interface ChoiceProviderProps {
children: (props: {
choices: SingleAutocompleteChoiceType[];
hasMore: boolean;
loading: boolean;
fetchChoices: (value: string) => void;
fetchMore: () => void;
}) => React.ReactElement<any>;
children: (
props: FetchMoreProps & {
choices: SingleAutocompleteChoiceType[];
fetchChoices: (value: string) => void;
}
) => React.ReactElement;
choices: SingleAutocompleteChoiceType[];
}
interface ChoiceProviderState {
choices: SingleAutocompleteChoiceType[];
filteredChoices: SingleAutocompleteChoiceType[];
first: number;
loading: boolean;
timeout: any;
}
const step = 5;
const loadingTime = 400;
export class ChoiceProvider extends React.Component<
ChoiceProviderProps,
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 interface UseMockChoiceProviderOpts extends FetchMoreProps {
fetchChoices: (value: string) => void;
}
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
});
};