mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-10-07 00:07:07 +00:00
Improve createConnector definition
This commit is contained in:
+10
-2
@@ -116,6 +116,10 @@ export interface ConnectorDescription<TProvided, TExposed> {
|
||||
cleanUp?(this: React.Component<TExposed>, props: TExposed, searchState: SearchState): SearchState;
|
||||
}
|
||||
|
||||
export type ConnectorProvided<TProvided> = TProvided &
|
||||
{ refine: (...args: any[]) => any, createURL: (...args: any[]) => string } &
|
||||
{ searchForItems: (...args: any[]) => any }
|
||||
|
||||
/**
|
||||
* Connectors are the HOC used to transform React components
|
||||
* into InstantSearch widgets.
|
||||
@@ -128,8 +132,12 @@ export interface ConnectorDescription<TProvided, TExposed> {
|
||||
*/
|
||||
export function createConnector<TProvided = {}, TExposed = {}>(
|
||||
connectorDesc: ConnectorDescription<TProvided, TExposed>,
|
||||
): <TProps extends Partial<TProvided>>(Composed: React.ComponentType<TProps>) =>
|
||||
ConnectedComponentClass<TProps, TProvided, TExposed>;
|
||||
): (
|
||||
(stateless: React.StatelessComponent<ConnectorProvided<TProvided>>) => React.ComponentClass<TExposed>
|
||||
) & (
|
||||
<TProps extends Partial<ConnectorProvided<TProvided>>>(Composed: React.ComponentType<TProps>) =>
|
||||
ConnectedComponentClass<TProps, ConnectorProvided<TProvided>, TExposed>
|
||||
);
|
||||
|
||||
// Utils
|
||||
export const HIGHLIGHT_TAGS: {
|
||||
|
||||
@@ -20,7 +20,8 @@ import {
|
||||
connectAutoComplete,
|
||||
Hit,
|
||||
TranslatableProvided,
|
||||
translatable
|
||||
translatable,
|
||||
ConnectorProvided
|
||||
} from 'react-instantsearch-core';
|
||||
|
||||
() => {
|
||||
@@ -41,13 +42,7 @@ import {
|
||||
|
||||
// https://community.algolia.com/react-instantsearch/guide/Custom_connectors.html
|
||||
() => {
|
||||
interface Provided {
|
||||
query: string;
|
||||
page: string;
|
||||
refine: (newQuery: string, newPage: number) => void;
|
||||
}
|
||||
|
||||
const CoolWidget = createConnector<Provided>({
|
||||
const CoolWidget = createConnector({
|
||||
displayName: 'CoolWidget',
|
||||
|
||||
getProvidedProps(props, searchState) {
|
||||
@@ -73,9 +68,10 @@ import {
|
||||
queryAndPage: [newQuery, newPage],
|
||||
};
|
||||
},
|
||||
})((props: Provided) =>
|
||||
})((props) =>
|
||||
<div>
|
||||
The query is {props.query}, the page is {props.page}.
|
||||
This is an error: {props.somethingElse} { /* $ExpectError */}
|
||||
{/*
|
||||
Clicking on this button will update the searchState to:
|
||||
{
|
||||
@@ -102,6 +98,113 @@ import {
|
||||
</CoolWidget>;
|
||||
};
|
||||
|
||||
() => {
|
||||
interface Provided {
|
||||
query: string;
|
||||
page: number;
|
||||
}
|
||||
|
||||
interface Exposed {
|
||||
defaultRefinement: string;
|
||||
startAtPage: number;
|
||||
}
|
||||
|
||||
const typedCoolConnector = createConnector<Provided, Exposed>({
|
||||
displayName: 'CoolWidget',
|
||||
|
||||
getProvidedProps(props, searchState) {
|
||||
// Since the `queryAndPage` searchState entry isn't necessarily defined, we need
|
||||
// to default its value.
|
||||
const [query, page] = searchState.queryAndPage ||
|
||||
[props.defaultRefinement, props.startAtPage];
|
||||
|
||||
// Connect the underlying component to the `queryAndPage` searchState entry.
|
||||
return {
|
||||
query,
|
||||
page,
|
||||
};
|
||||
},
|
||||
|
||||
refine(props, searchState, newQuery, newPage) {
|
||||
// When the underlying component calls its `refine` prop, update the searchState
|
||||
// with the new query and page.
|
||||
return {
|
||||
// `searchState` represents the search state of *all* widgets. We need to extend it
|
||||
// instead of replacing it, otherwise other widgets will lose their
|
||||
// respective state.
|
||||
...searchState,
|
||||
queryAndPage: [newQuery, newPage],
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const TypedCoolWidgetStateless = typedCoolConnector((props) =>
|
||||
<div>
|
||||
The query is {props.query}, the page is {props.page}.
|
||||
This is an error: {props.somethingElse} { /* $ExpectError */}
|
||||
{/*
|
||||
Clicking on this button will update the searchState to:
|
||||
{
|
||||
...otherSearchState,
|
||||
query: 'algolia',
|
||||
page: 20,
|
||||
}
|
||||
*/}
|
||||
<button onClick={() => props.refine('algolia', 20)} />
|
||||
{/*
|
||||
Clicking on this button will update the searchState to:
|
||||
{
|
||||
...otherSearchState,
|
||||
query: 'instantsearch',
|
||||
page: 15,
|
||||
}
|
||||
*/}
|
||||
<button onClick={() => props.refine('instantsearch', 15)} />
|
||||
</div>
|
||||
);
|
||||
|
||||
<TypedCoolWidgetStateless
|
||||
defaultRefinement={'asdf'}
|
||||
startAtPage={10}
|
||||
/>;
|
||||
|
||||
const TypedCoolWidget = typedCoolConnector(
|
||||
class extends React.Component<ConnectorProvided<Provided> & { passThruName: string }> {
|
||||
render() {
|
||||
const props = this.props;
|
||||
return <div>
|
||||
The query is {props.query}, the page is {props.page}.
|
||||
The name is {props.passThruName}
|
||||
{/*
|
||||
Clicking on this button will update the searchState to:
|
||||
{
|
||||
...otherSearchState,
|
||||
query: 'algolia',
|
||||
page: 20,
|
||||
}
|
||||
*/}
|
||||
<button onClick={() => props.refine('algolia', 20)} />
|
||||
{/*
|
||||
Clicking on this button will update the searchState to:
|
||||
{
|
||||
...otherSearchState,
|
||||
query: 'instantsearch',
|
||||
page: 15,
|
||||
}
|
||||
*/}
|
||||
<button onClick={() => props.refine('instantsearch', 15)} />
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
<TypedCoolWidget
|
||||
defaultRefinement={'asdf'}
|
||||
startAtPage={10}
|
||||
passThruName={'test'} />;
|
||||
|
||||
};
|
||||
|
||||
() => {
|
||||
interface StateResultsProps {
|
||||
searchResults: SearchResults<{
|
||||
|
||||
Reference in New Issue
Block a user