Algolia: Export React Instant Search results - reactjs

Is there any way to export Algolia's React Instant Search results to a CSV? I've tried using the react-csv package, but it doesn't work with Algolia's Hit Component. The package requires data as props, but the data is constantly changing since it's React Instant Search.
What I mean by constantly changing is that on page load, you're given the entire index of records found, then you can narrow down the results with the search bar or other filtering components.
I've gone down the Google rabbit hole looking for information about exporting Algolia's search results as a CSV, but I haven't found anything regarding React Instant Search—unless I completely missed it.
Has anyone tried this before? If so, could you point me in the right direction regarding documentation or examples?

Not sure if this solves your problem but one possible way is to use the StateResults widget. The StateResults widget provides a way to access the searchState and the searchResults of InstantSearch.
Here I will create a custom StateResults component in the form of a download button and then connect it using the connectStateResults connector.
I have attached a demo below as well.
For simplicity I didn't format the data to be fed into the CSV builder.
// 1. Create a React component
const StateResults = () => {
// return the DOM output
};
// 2. Connect the component using the connector
const CustomStateResults = connectStateResults(StateResults);
// 3. Use your connected widget
<CustomStateResults />
In your case something like
const StateResults = ({ searchResults }) => {
const hits = searchResults?.hits;
return (
<div>
<button>{hits && <CSVLink data={hits}>Download CSV</CSVLink>}</button>
</div>
);
};
const DownloadButton = connectStateResults(StateResults);
//in your JSX then <DownloadButton />

Related

React Context always returns EMPTY

I have a Search parent component and a SideBar child component, I am trying to get context in SideBar, but everytime it returns empty.
I followed the tutorial exactly like: https://itnext.io/manage-react-state-without-redux-a1d03403d360
but it never worked, anyone know what I did wrong?
Here is the codesandbox link to the project: https://codesandbox.io/s/vigilant-elion-3li7v
I wrote that article.
To solve your specific problem:
When using the HOC withStore you're injecting the prop store into the wrapped component: <WrappedComponent store={context}.
The value of the prop store is an object that contains 3 functions: get, set, and remove.
So, instead of printing it, you should use it. For example this.props.store.get("currentAlbums") or this.props.store.set("currentAlbums", [album1, album2]).
This example is forked by your code: https://codesandbox.io/s/nameless-wood-ycps6
However
Don't rewrite the article code, but use the library: https://www.npmjs.com/package/#spyna/react-store which is already packed, tested, and has more features.
An event better solution is to use this library: https://www.npmjs.com/package/react-context-hook. That is the new version of the one in that article.
This is an example of a sidebar that updates another component content: https://codesandbox.io/s/react-context-hook-sidebar-xxwkm
Be careful when using react context API
Using the React Context API to manage the global state of an application has some performance issues, because each time the context changes, every child component is updated.
So, I don't recommend using it for large projects.
The library https://www.npmjs.com/package/#spyna/react-store has this issue.
The library https://www.npmjs.com/package/react-context-hook does not.
You pass the store as a prop, so to access it, you need this.props.store in your SideBar.
Not this.state.store
Create a wrapping App component around Search and Sidebar:
const App = props => (
<div>
<Search />
<SideBar />
</div>
);
export default createStore(App);
Now you can manipulate state with set and get that you have available in child components Search and Sidebar.
In Search component you can have something like:
componentDidMount() {
this.props.store.set("showModal", this.state.showModal);
}
also wrapped with withStore(Search) ofc.
and in SideBar you can now call:
render() {
return (
<div>
{"Sidebar: this.state.store: ---> " +
JSON.stringify(this.props.store.get("showModal"))}
}
</div>
);
}
and you will get the output.

querying stripe api & display image

I have been following a tutorial to query Stripe API and display data. One thing that is not mentioned is how to query the images and display it. I can see from the structure that the images property is there but I need some help to display it. I assume it should be the same logic how it is displaying the product name but I just need to understand to follow the same logic for the images.
Here is my query, I have added the image option in my query:
and can see the result in GrapiQL:
Here is example of how I am mapping over my products to display correctly. From what I understand I need to do the same for the image. I have followed the same logic by just replacing product with image but just can't seem to get it working. Here is the snippet:
const Products = () => {
return (<StaticQuery query={PRODUCTS_QUERY}
render={
({ allStripeSku, allStripeProduct }) => {
return allStripeProduct.edges.map(product => {
const skus = allStripeSku.edges.filter(
sku => sku.node.product.id === product.node.id
)
return (
<Product
key={product.node.id}
skus={skus}
product={product.node} />
)
})
return
}
}
/>)
}
Can anyone please point my in the right direction so I can get this working?
You need to add 2 lines of code:
in GraphQL query to return images alongside id and name as you've already done
in ProductCard component to return an <img> element using the query field added above
For me this meant adding the + lines below:
in src/components/Products/Products.js
in src/components/Products/ProductCard.js
I assume it's the Gatsby E-commerce Tutorial you were following; if so please be aware that, since your OP, they've updated the docs so it no longer uses the deprecated Orders API.

ReactTable and custom server side data update

Has anybody ever used this awesome react components processing server side data?
The solution given here is excellent if you don't need to manually update the data.
I would need to refresh the data not only when changing page/pageSize/sorting/filtering, but also after some intervalled time, to see if data got changed.
Also I have an extension of the table that allows the user to do a full text search on all columns so I would need to update the data when the user changes the content of the custom search box too.
I had the same problem as yours and I started looking for asynchronous tests with ReactJs and I found this article that was very useful. The key part was to use "update" method on the Enzyme component, like below:
const items = ['die Straße', 'die Adresse', 'die Nationalität'];
jest.useFakeTimers();
describe('<DelayedList />', () => {
test('it renders the items with delay', () => {
const component = shallow(
<DelayedList items={items} />
);
jest.runAllTimers();
component.update(); // <--- force re-render of the component
expect(component.state().currentIndex).toEqual(items.length);
expect(component).toMatchSnapshot();
});
For more information, see this medium article.

How to Jump to Redux State with Browser Back Button

I’m a react beginner and I have a project using React Router (4.2.2), Redux and I’ve recently added react-router-redux hoping that it would solve my problem. I have components whose redux stored states need to change based on interactions with the browser back and forward buttons.
For example, I have a screen containing details for an element the user clicked. If I use the browser back button and navigate to another point in history in which that details view was open, it will only show the most recent element info (due to that the only information in the store) or sometimes no information at all will be passed.
I thought react-router-redux would help me keep these two in sync but maybe I’m missing a step that enables that to happen. I’ve installed Redux Debug Tools and I can see in there the state that I want to jump to, but how do I enable it when the user uses the back button? The url for the details page is the same each time it’s viewed, perhaps I need to add a hash tag with specific information but even then, how would I do a look up for the correct information in the store?
I open the details view like this:
<Link to='/activityDetails'>
<ActivityButton
id={this.props.someData.someId}
/>
</Link>
And inside ActivityButton:
openActivityDetails = () => {
this.props.showActivityDetailsScreen(this.props.id);
};
function matchDispatchToProps(dispatch) {
return bindActionCreators({
showActivityDetailsScreen: activityDetailsActions.showActivityDetails
}, dispatch)
}
render(){
return (
<div className={'activity-button'} onClick={this.openActivityDetails}>
<img
onClick={this.handleClick}
src={imgPath}
/>
</div>
);
}
So I figured it out on my own. Essentially what you need to do is set the state information inside the when you create it, like so:
<Link to={{
pathname: '/activityDetails',
state: { "activityData": activityData }
}}>
<ActivityButton
id={this.props.someData.someId}
/>
</Link>
then in the class you need the information ActivityDetails in my case you can query it like this:
var actData = this.props.location.state.activityData;
or if you're using withRouter and history it's also in the following location:
const { history: { push } } = this.props;
history.state.state.activityData
I ended up removing react-router-redux because it wasn't necessary. It made an entry in the state with the current route, but in my case that wasn't useful. Hope this helps someone in the future.

How use N views in sample app in react native

I have some doubt in React Native. I read this answer (How to do a multi-page app in react-native?) but I stayed with a little bit doubt:
I use Navigator to many views in React Native App, but how I do to N componentes? For example, if I have 5 different views I have use the before code five times... and n times?
to ellude more on my comment.
instead of this
if (routeId === 'SplashPage') {
return (
<SplashPage
navigator={navigator}/>
);
}
if (routeId === 'LoginPage') {
return (
<LoginPage
navigator={navigator}/>
);
}
just have a hashtable that you use to get the component dynamically.
const Component = VIEW_COMPONENTS[routeid];
so your code would look something like this
const VIEW_COMPONENTS = {
'SplashPage': SplashPage,
'LoginPage': LoginPage
};
renderScene = ( route, navigator ) => {
const ViewComponent = VIEW_COMPONENTS[route.id];
return <ViewComponent navigator={navigator}/>
}
any additional screen would be a single line entry to your lookup table. I have a native app with 40 screens and its very easy to manage like this
to add to this. you can abstract more out of this too. make every view not care about where it is used or what its next view is. Instead make all of that a part of your lookup object. specify a next route that every view can show. you can pass any additional information all of which is configurable and your screens can be reused on multiple flows!

Resources