Material UI - Google Maps Autocomplete - Restrict to city and state? - reactjs

I'm using the Google Maps Places Autocomplete that comes with Material UI and I'm stuck on trying restrict the results. When a user starts typing the only suggestions I want returned are City, State for them to select.
Here is a link to MUI's documentation with example:
Material UI - Google Places Autocomplete
Thanks!

It looks like the code from the library is using the AutocompleteService.getPlacePredictions. To achieve your use case you need to include the types properties with value of ['(cities)'] to your AutocompleteService.getPlacePredictions request. This will instructs the Places service to return results that match locality or administrative_area_level_3 as stated here
You can add it inside the fetch in the code sample just like below:
fetch({ input: inputValue, types: ['(cities)'] }, (results) => {
if (active) {
let newOptions = [];
if (value) {
newOptions = [value];
}
if (results) {
newOptions = [...newOptions, ...results];
}
setOptions(newOptions);
}
});
Here's the sample code. Make sure to use your API key for the sample to work.

Related

Mapbox React queryTerrainElevation returns null

I am attempting to get the elevation of certain coordinates on the map using mapbox.
Based on the documentation, i can use queryTerrainElevation.
Sample Code:
map.on("click", (data) => {
console.log(data);
const elevation = map?.queryTerrainElevation(data.lngLat, {
exaggerated: true,
});
console.log("Elevation: " + elevation)
});
Console logs:
Using the mapbox tilequery with the same coordinates:
https://api.mapbox.com/v4/mapbox.mapbox-terrain-v2/tilequery/95.9345,41.2565.json?access_token=<mapbox_token>
There is an elevation value in the response:
You must be adding the custom layer after just loading the style. So, the terrain value isn't updated at that time. That's why you get null.
Do it like this and it should work.
map.on('idle', () => {
const elevation = map.queryTerrainElevation(coordinates, {exaggerated: false});
})
This runs the layer code after the map is loaded. Instead of just the style.

How to set value of React Material UI Slider via Cypress?

I'm using slider from here: https://material-ui.com/components/slider/
Trying to set it's value like:
cy.get("[data-cy=slider-population]")
.as("range")
.invoke("val", val)
.trigger("change");
However it's not moving. Anyone manage to get this working?
To make it a bit simpler for future viewers, #kevin's answer points you to all the right places to extract a working test, however here's everything without their demo code:
<Slider data-cy="slider-population" />
First, you need to add this command:
Cypress.Commands.add("reactComponent", {
prevSubject: "element"
}, ($el) => {
if ($el.length !== 1) {
throw new Error(`cy.component() requires element of length 1 but got ${$el.length}`);
}
// Query for key starting with __reactInternalInstance$ for React v16.x
const key = Object.keys($el.get(0)).find((key) => key.startsWith("__reactFiber$"));
const domFiber = $el.prop(key);
Cypress.log({
name: "component",
consoleProps() {
return {
component: domFiber,
};
},
});
return domFiber.return;
});
Then in your test if you want to set the minimum to 0, and the max to 15:
cy.get('[data-cy="slider-population"]')
.reactComponent()
.its("memoizedProps")
.invoke("onChange", null, [0, 15]);
There is an example in the Cypress Real World App, a payment application to demonstrate real-world usage of Cypress testing methods, patterns, and workflows which demonstrates this for it's purposes.
cy.setTransactionAmountRange is a command built to interact with the Material UI Slider.
It uses another Cypress custom command, cy.reactComponent to gain access to the component internals and allow methods like onChange to be invoked directly on the component instance.
Here's a spartan riff on the solution provided by Shannon Hochkins.
Usage:
cy.get("[data-cy=slider-population]")
.setSlider([0,15])
Command:
Cypress.Commands.add('setSlider', { prevSubject: 'element' },
(subject, value) => {
const key = Object.keys(subject.get(0))
.find((key) =>
key.startsWith("__reactFiber$"))
const fiberNode = subject.prop(key)
fiberNode.return.memoizedProps.onChange(null, value)
return subject
})
Typescript:
declare namespace Cypress {
interface Chainable {
setSlider(value: number | number[]): Chainable<void>
}
}

React Navigation 4.x to React Navigation 5.x

The current problem I have is that i want to use navigation parameters to update the state
The tutorial in the link above uses React Navigation 4.x while I use React Navigation 5.x
Tutorial:
function onSaveNote() {
navigation.state.params.addNote({ noteTitle, noteValue })
navigation.goBack()
}
MyProject:
function onSaveAuction() {
navigation.navigate('Home', { auctionTitle, auctionValue }
}
This is the warning I would get whenever I used used the code for 4.x
I have tried using the second bullet point which is to use navigate instead but it still does not seem to work.
Any help would be appreciated.
There is nothing wrong with the syntax(except for the bracket you forgot to close). Your problem is with the data you are trying to pass. The warning tells you that you are trying to pass non-serializable values such as class instances, functions etc. So check again what are the values of auctionTitle and auctionValue.
We don't know your data, however you shouldn't pass functions or class in nav params.
To make sure that your data doesn't have non-serializable data, as mentioned above, you can try do a JSON.stringify(), then JSON.parse in next screen to see if this warning disappears.
The best solution is to check your data, but if you need to pass non-serializable data, feel free to use JSON.
I made a example to you:
Passing params:
function onSaveAuction() {
/* It will remove any functions, class or other non-serializable from params. */
const data = JSON.stringify({ auctionTitle, auctionValue });
navigation.navigate('Home', { data });
}
Home.js
function Home({ route, navigation }) {
/* Get the param, then parse to object */
const data = JSON.parse(route.params.data);
}

How does document.getSelection work under reactjs environment?

I was working on a electron-react project for epub file. Right now, I am planning to make the app capable of selecting text field and highlight it.
To achieve it, I was trying to use web's Window.getSelection api. However, there are some really weird things come up like in this.
In short, I am unable to capture the Selection object. It seems like even if I log the Selection object, this object could somehow jump to something else. Also, I cannot even serialize the Selection object with JSON.stringfy. This is super surprising, and this is my first time seeing something like this (I will get empty object to stringfy the Selection object).
So how to use Window.getSelection properly under react-electron environment? Or this api will not work well for text content which is generated by react's dangerouslySetInnerHTML?
Looks like the window.getSelection api needs to toString the selected object.
const getSelectionHandler = () => {
const selection = window.getSelection();
console.log("Got selection", selection.toString());
};
Super simple textarea and button to get selection react demo
this solution might help someone, catch last selection
const selection = useRef('');
const handleSelection = () => {
const text = document.getSelection().toString();
if (text) {
selection.current = text;
}
}
useEffect(() => {
document.addEventListener('selectionchange', handleSelection);
return () => {
document.removeEventListener('selectionchange', handleSelection);
};
});

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.

Resources