Closed njt1982 closed 7 years ago
It doesn't look horrifically different to https://github.com/algolia/react-instantsearch/blob/master/stories/Menu.stories.js
ok so react-instantsearch/native
doesn't export a Menu... So that explains that error, I think? https://github.com/algolia/react-instantsearch/blob/master/packages/react-instantsearch/native.js
So importing from dom causes this:
ok, current progress...
Instead of <Menu... />
I'm now doing <ConnectedEventsFilter attributeName="events" />
along with this:
class EventsFilter extends Component {
render() {
console.log(this);
return (<Text>EventsFilter</Text>);
}
}
const ConnectedEventsFilter = connectRefinementList(EventsFilter);
Pro points:
this.props.items
as an array of facet items with count and label....Con points:
I feel like I am missing something here (or, more accurately, several pages from the documentation are missing! ;) ).
I quite literally stumbled on this approach by finding this issue: https://github.com/algolia/instantsearch.js/issues/2069 Which involves @Arcade1080 and @Haroenv
Problem is, they are doing this:
// Modal Content
import CurrentRefinements from './currentrefinements';
import CategoryFilter from './categoryfilter';
import SizeFilter from './sizefilter';
import ApplyFilter from './applyfilter';
// Pass Components to Algolia Connectors
const ConnectedHits = connectInfiniteHits(Hits);
const ConnectedCurrentRefinements = connectCurrentRefinements(CurrentRefinements);
const ConnectedCategoryFilter = connectHierarchicalMenu(CategoryFilter);
const ConnectedSizeFilter = connectRefinementList(SizeFilter);
const ConnectedApplyFilter= connectStats(ApplyFilter);
But I have no idea what is in ./categoryfilter
- Does that subclass component with a custom renderer?!
IF this is the approach to take, what is the point of all those components and widgets?!
hmmm so this error:
Seems to indicate that something is using non-react elements (https://stackoverflow.com/a/38238220/224707)...
It looks like using one of the provided components does not use React Native elements... https://github.com/algolia/react-instantsearch/blob/9afd0eff249c87379c66fefbdaf549483ea37272/packages/react-instantsearch/src/components/RefinementList.js
So does this mean we cannot use the provided widgets?
Ok so THIS lets me render a facet out using Native Base CheckBox's...
class CheckboxRefinementListComponent extends Component {
render() {
return (
<List dataArray={this.props.items}
renderRow={(row) => <ListItem><CheckBox checked={row.isRefined} /><Text>{row.label}</Text></ListItem>} />
);
}
}
const ConnectedCheckboxRefinementList = connectRefinementList(CheckboxRefinementListComponent);
But my problem now is trying to get it into a Drawer...
<Container>
<Drawer ref={(ref) => { this.drawer = ref; }}
content={<Content bounces={false} style={{backgroundColor: 'white', padding: 15}}>
<ConnectedCheckboxRefinementList attributeName="events" />
</Content>}
side="right"
onClose={() => this.hideFacetDrawer()}>
<InstantSearch
appId="[ID]"
apiKey="[KEY]"
indexName="[INDEX]">
<ConnectedSearchBox toggleFacetDrawer={() => this.toggleFacetDrawer() } />
<VirtualMenu attributeName="search_type" defaultRefinement={'contact'} />
<ConnectedHits navigation={this.props.navigation}/>
</InstantSearch>
</Drawer>
</Container>
However, this throws errors due to the ConnectedCheckboxRefinementList
not being able to pickup the context from the InstantSearch
(as its outside it).
If I invert those wrappers (so Drawer is inside the InstantSearch), then the Drawer is not rendered properly.
HI @njt1982,
Thank you for all this feedback. Actually we do not provide react native widgets yet, so you can only use connectors. It means that you need to implement your own Menu
using the connectMenu
connector. Also, our connectors can't be used outside an <InstantSearch/>
instance. Because you're trying to implement a react native app you'll have to use multiple <InstantSearch/>
instance and share the searchState
between the instances by listening to the onSearchStateChange
(a function you can provide to InstantSearch). Also, please note that to be applied a refinement needs to have its proper widgets mounted, so you'll need to use VirtualWidgets
.
Here are some guides:
We are currently working on a getting started guide dedicated to React Native. It's not ready yet, but you can find the an in progress example of a complete react native application here to see those concepts in action: https://github.com/algolia/react-instantsearch/tree/docs/improve-react-native-example/packages/react-instantsearch/examples/react-native
Thanks @mthuret - the way I got around the nesting problem (at 1.30am last night!) was to add this to one of my elements inside InstantSearch ref={(ref) => { this.vm = ref; }}
- then my Drawer content is rendered from a method which checks for the presense of this.vm
. If its not present/set yet then it bails and returns null. If it is set, then it renders the custom widgets inside a wrapper which passes in some context as a property.
<DrawerContentWrapper ais={this.vm.context.ais} >
This is a custom component like this:
class DrawerContentWrapper extends Component {
constructor(props) {
super(props);
this.state = {
ais: props.ais
};
}
getChildContext() {
return {
ais: this.state.ais
};
}
render = () => this.props.children
}
DrawerContentWrapper.childContextTypes = {
ais: PropTypes.object.isRequired,
multiIndexContext: PropTypes.object,
}
I'm 99.9% sure this is a hack and not the "React Way". But it works ;) Or at least seems to so far...
I'm intrigued by the multiple InstantSearch wrappers approach and syncing the state between them, although tbh I think that feels like just as much of a hack solution as passing the context out of a nested stack and into a different sub-stack via properties and wrapper 😆 (and I mean "hack" in terms of "not a nice solution" as opposed to anything offensive).
I VERY nearly got the Drawer working inside the InstantSearch. The problem was the Hits section. If I manually rendered a List with some ListItems and Text (to fake some results), it all worked fine, but as soon as I put those fake results (or real results) inside a connected Hit component, they just wouldn't render and the Drawer stopped functioning properly.
You should definitely not pass any context as props as its internal and can be changed but use another <InstantSearch/>
instance inside your drawer :) You'll also have to use a VirtualSearchBox and a VirtualMenu inside the drawer.
In the example I gave you you'll find how we sync the searchState
between different screen. Even though here it's just a drawer you can use the same strategy.
I'm not sure to get what happen when using the connectHits
connector. Do you have any errors?
No errors, no - but it just didn't render the hits (a white area). I think it WAS rendering them somewhere, but the layout was all wrong. And the draw came in from the side as a 10px high bar and there was no grey overlay (or underlay?!). If I removed the hits, it all rendered fine (but obviously without any result set!). I messed around with all the flex stuff for hours, no luck.
I'll have a look at your examples. Thanks.
Let me know how it goes. If you're still stuck maybe sharing a repo with the issue could be easier :)
@mthuret Thank you for the tips! Passing the searchState around has simplified things a lot. Fewer wrappers ;) Hopefully, if anyone else hits this issue before it's been documented properly, they'll find this thread ;)
However, I'm still not 100% sold on having to configure an InstantSearch in multiple places. It seems to mean "duplicating" settings like appId
, appKey
and indexName
.
You can have a configuration file with those in order to not repeat them everywhere :)
@mthuret the issue I have now is that I can search in the SearchBox and I can refine from my Drawer (and these refinements apply to the Hits)... However the query from the SearchBox is not being passed to the Refinements. I can see it's being propagated via state.searchState to the Drawer, am I also meant to pass that state into the connectedRefinementList's?
@njt1982: I'm pretty sure you miss the virtual SearchBox under the <InstantSearch/>
instance of the drawer. Having a refinement in the searchState
is not enough to be applied, you'll also need the corresponding widget to be mounted.
I'm closing this, feel free to reopen it @njt1982 if you still have issues.
I'm trying to implement the
Menu
(https://community.algolia.com/react-instantsearch/widgets/Menu.html) on my app but getting a JS error about the element type being invalid (got undefined, likely forgot to export your component).This all works fine if I remote
Menu
.I'm clearly doing something wrong, but I cannot find any documentation about using a Menu facet/filter on react native. They all seem to import from the "dom" side of things, which doesn't work on native (or at least doesn't seem to). Ideally this Menu will eventually live under the
FacetSidebar
view.Any ideas?