Do you want to request a feature or report a bug?
feature request.
Feature: What is your use case for such a feature?
Our use case is to support customized columns, for example:
// Search Component
class App extends React.Component {
render() {
const { columns } = this.state;
return (
<InstantSearch
appId="latency"
apiKey="3d9875e51fbd20c7754e65422f7ce5e1"
indexName="bestbuy"
>
<Search/>
<Hits hitComponent={HitComponent} hitComponentProps={{ columns }}
</InstantSearch>
);
}
}
// HitComponent
class HitComponent extends React.PureComponent {
render() {
const { hit, columns } = this.props;
return (
<div>
{columns.map(column => (<div key={column}>{hit[column]}</div>))
</div>
};
}
}
What project are you opening an issue for?
Hi @springuper, what about you do this:
// Search Component
class App extends React.Component {
render() {
const { columns } = this.state;
return (
<InstantSearch
appId="latency"
apiKey="3d9875e51fbd20c7754e65422f7ce5e1"
indexName="bestbuy"
>
<Search/>
<Hits
hitComponent={hit => <HitComponent hit={hit} columns={this.state.columns} />}
/>
</InstantSearch>
);
}
}
const HitComponent = ({hit, columns}) =>
<div>
{columns.map(column => <div key={column}>{hit[column]}</div>}
</div>;
?
it's good enough for me, thanks!
Hi,
The solution above works fine by itself, however when I try to wrap <Hits/> using connectStateResults, the application freezes completely and the <Drug/> component is rendered in an infinite loop. Here is the code I'm trying:
function Search({ onDrugClicked }) {
return (
<div>
<div style={{ margin: "auto" }}>
<SearchBox />
</div>
<ListGroup className="mt-2">
<Content onDrugClicked={onDrugClicked} />
</ListGroup>
</div>
);
}
var Drug = ({ hit, onDrugClicked }) => {
return (
<ListGroupItem onClick={onDrugClicked}>
<DrugCard drug={hit} />
</ListGroupItem>
);
};
const Content = connectStateResults(({ searchState, onDrugClicked }) => {
return searchState && searchState.query ? (
<Hits
hitComponent={({ hit }) => (
<Drug hit={hit} onDrugClicked={() => onDrugClicked(hit)} />
)}
/>
) : (
<div className="text-muted" />
);
});
export default () => (
<InstantSearch
appId="xxxxxxxxxx"
apiKey="xxxxxxxx"
indexName="drugs"
>
<Configure hitsPerPage={15} />
<Search onDrugClicked={hit => console.log(hit)} />
</InstantSearch>
);
However, when I remove the connectStateResults connector, it works as expected:
function Search({ onDrugClicked }) {
return (
<div>
<div style={{ margin: "auto" }}>
<SearchBox />
</div>
<ListGroup className="mt-2">
<Content onDrugClicked={onDrugClicked} />
</ListGroup>
</div>
);
}
var Drug = ({ hit, onDrugClicked }) => {
return (
<ListGroupItem onClick={onDrugClicked}>
<DrugCard drug={hit} />
</ListGroupItem>
);
};
const Content = ({ searchState, onDrugClicked }) => {
return true ? (
<Hits
hitComponent={({ hit }) => (
<Drug hit={hit} onDrugClicked={() => onDrugClicked(hit)} />
)}
/>
) : (
<div className="text-muted" />
);
};
export default () => (
<InstantSearch
appId="xxxxxxxx"
apiKey="xxxxxxxxxxx"
indexName="drugs"
>
<Configure hitsPerPage={15} />
<Search onDrugClicked={hit => console.log(hit)} />
</InstantSearch>
);
Any help is appreciated!
@korroktheslavemaster Seeing the same thing. My Guess is that has to do with passing an anonymous function is creating a new instance of the component every render.
@prescottprue is correct, @vvo's suggestion should be avoided as it's a killer for performance because react sees the function as a new component and therefore mounts and unmounts on each render instead of diffing.
This can be seen by logging in componentDidMount() { console.log('didMount') } or useEffect(() => console.log('didMount'), []).
Most component APIs support passing in componentProps as the OP has suggested or alternatively support a render prop.
In the meantime I've used a custom Hits component as a workaround:
import { connectHits } from 'react-instantsearch-dom';
const Hits: React.FunctionComponent<Props> = ({
hits,
active
}) => {
return (
<ol style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gridGap: '10px', gridAutoRows: '1fr' }}>
{hits.map(hit => <li key={hit.objectID}>{hit.objectID} {active}</li>)}
</ol>
);
};
export default connectHits(Hits);
Most helpful comment
Hi @springuper, what about you do this:
?