Could u have a look? no map appeared
https://codepen.io/DeanWinchester88/pen/BaZYewv
async function chart() {
const [data,geo] = await Promise.all([
d3.json(promises[0]),
d3.json(promises[1])
])
console.log("data",data)
console.log("geo", geo)
}
chart()
let path = d3.geoPath()
function ready(error,data,geo){
//topojson object
let topoobject = topojson.feature(geo, geo.objects.counties);
let counties = topoobject.features;
You need to pass the data to the ready function. Right now in your code, the ready function is never called. You can do it like this:
Promise.all([
d3.json(EDUCATION),
d3.json(COUNTIES),
]).then(([data, geo]) => {
ready(null, data, geo);
});
Also, there is a mistake in the EDUCATION url. It should be:
const EDUCATION = "https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/for_user_education.json";
const COUNTIES = "https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/counties.json";
Lastly, the first line of ready misspells topojson.
Related
I am writing a simple application using React to fetch and display data from the Star Wars API. I first fetch information about a particular planet. The response JSON for a given planet contains a bunch of data, including an array of URLs pointing to further data about notable residents of said planet. I next call each of those URLs in order to display a list of the names of the residents of the current planet.
This code works, but is slow as heck:
const url = `https://swapi.dev/api/planets/`;
const [currentPlanetNumber, setCurrentPlanetNumber] = React.useState(1);
const [currentPlanet, setCurrentPlanet] = React.useState({});
const [currentPlanetResidentsDetails, setCurrentPlanetResidentsDetails] =
React.useState([]);
React.useEffect(() => {
(async () => {
const planetData = await fetch(`${url}${currentPlanetNumber}/`).then(
(response) => response.json()
);
setCurrentPlanet(planetData);
if (planetData.residents.length === 0) {
setCurrentPlanetResidentsDetails(["No notable residents"]);
} else {
const residentsURLs = planetData.residents;
const residentsNames = await Promise.all(
residentsURLs.map(async (item) => {
const name = await fetch(item).then((response) => response.json());
const newName = name.name;
return newName;
})
);
setCurrentPlanetResidentsDetails(residentsNames);
}
})();
}, [currentPlanetNumber]);
The following code works fairly fast for this:
const url = `https://swapi.dev/api/planets/`;
const [currentPlanetNumber, setCurrentPlanetNumber] = React.useState(1);
const [currentPlanet, setCurrentPlanet] = React.useState({});
const [currentPlanetResidentsDetails, setCurrentPlanetResidentsDetails] =
React.useState([]);
React.useEffect(() => {
(async () => {
const planetData = await fetch(`${url}${currentPlanetNumber}/`).then(
(response) => response.json()
);
setCurrentPlanet(planetData);
})();
}, [currentPlanetNumber]);
React.useEffect(() => {
(async () => {
if (currentPlanet.residents.length === 0) {
setCurrentPlanetResidentsDetails(["No notable residents"]);
} else {
const residentsURLs = currentPlanet.residents;
const residentsNames = await Promise.all(
residentsURLs.map(async (item) => {
const name = await fetch(item).then((response) => response.json());
const newName = name.name;
return newName;
})
);
setCurrentPlanetResidentsDetails(residentsNames);
}
})();
}, [currentPlanet]);
What makes the second one so much faster? I assumed that they would both take about the same length of time, because the same number of fetch requests get done either way.
Is it a good rule of thumb to not have more than one fetch request an any given useEffect hook?
No, there is no rule of thumb stating not to have more than one fetch request in a given useEffect.
In your first example, the fetch requests are fired consecutively, while in the second example they are fired concurrently.
Your first example seems to be more appropriate than the second. In the second example, it seems to you that the code is executing faster because both effects are firing concurrently when the component mounts. On subsequent changes to 'currentPlanetNumber', both examples should execute in the same amount of time.
My view should return multiple elements, but I always got only one.
I am calling my view with /vm-values/query.
Should I use another gateway endpoint for the MultiValueEncoded view?
To resolve this issue, I used the queryContract function from the class ApiNetworkProvider in the erdjs npm package.
const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.elrond.com");
const output = await apiNetworkProvider.queryContract({
address: "erd1....",
func: {
toString(): string {
return "myFunc";
}
},
getEncodedArguments() {
return []; // I don't need args
},
});
The returnData is encoded in base64, so I decoded like so:
const decodedData = output.returnData.map(data => Buffer.from(data, "base64").toString());
I am trying to add a search field for an address using google's address autocomplete in a Stenciljs component. There aren't any resources on it.
First you'll need to load the google maps api script, so that you can interact with the global google.maps object. You can either do that by including a script tag, or write something like the following helper function.
const googleApiKey = '...';
export const importMapsApi = async () =>
new Promise<typeof google.maps>((resolve, reject) => {
if ('google' in window) {
return resolve(google.maps);
}
const script = document.createElement('script');
script.onload = () => resolve(google.maps);
script.onerror = reject;
script.src = `https://maps.googleapis.com/maps/api/js?key=${googleApiKey}&libraries=places`;
document.body.appendChild(script);
});
In order to get the TypeScript types for the global google object, you should install #types/googlemaps into your dev-dependencies.
Then you'll need to implement a function that allows you to search for places, e. g.:
export const searchForPlaces = async (input: string, sessionToken: google.maps.places.AutocompleteSessionToken) => {
const maps = await importMapsApi();
const service = new maps.places.AutocompleteService();
return new Promise<google.maps.places.AutocompletePrediction[]>((resolve) =>
service.getPlacePredictions({ input, sessionToken }, (predictions, status) => {
if (status !== maps.places.PlacesServiceStatus.OK) {
return resolve([]);
}
resolve(predictions);
}),
);
};
None of this is specific to Stencil btw. All that is left to do is to use the searchForPlaces function in your component. A very simple example would be something like:
#Component({ tag: 'maps-place-search' })
export class MapsPlaceSearch {
sessionToken: string;
#State()
predictions: google.maps.places.AutocompletePrediction[];
async componentWillLoad() {
const maps = await importMapsApi();
this.sessionToken = new maps.places.AutoCompleteSessionToken();
}
async search = (e: InputEvent) => {
const searchTerm = e.target.value;
if (!searchTerm) {
this.predictions = [];
return;
}
this.predictions = await searchForPlaces(searchTerm, this.sessionToken);
}
render() {
return (
<Fragment>
<input onInput={this.search} />
<ul>
{this.predictions.map(prediction => <li key={prediction.description}>{prediction.description}</li>)}
</ul>
<Fragment>
);
}
}
The place search will give you a placeId for each prediction. That and the session token you can pass on to a maps.places.PlacesService to get the details for the place and auto-fill your form or whatever you're trying to achieve.
Please take a look this image. Want to know how could I do this using cypress?
You can use something like this depending on what exactly are you looking for:
cy.get('table')
.find('tbody tr')
.then(trs => {
const content = [];
Cypress.$(trs).each((_, tr) => {
const row = [];
const tds = Cypress.$(tr).find('td');
Cypress.$(tds).each((_, td) => {
const text = Cypress.$(td)
.contents()
.last()
.text();
row.push(text);
});
content.push(row);
});
console.log(content);
});
I have a simple saga of this form:
const getAccountDetails = function * () {
const { url } = yield select(state => state.appConfig)
const accountDetails = yield call(apiFetchAccountDetails, url)
}
I'm trying to write a unit test:
describe('getAccountDetails', () => {
const iterator = getAccountDetails()
it("should yield an Effect 'select(state=> state.appConfig)'", () => {
const effect = iterator.next().value
const expected = select(state => state.appConfig)
expect(effect).to.deep.eql(expected)
})
This test fails. Although effect and expected are very similar, they are not identical.
At least one of the differences is buried in payload.selector.scopes, where the yielded effect and expected are as follows:
As the scopes of these two will always be different, how can these tests ever be made to work?
eta: this pattern is adapted from the example linked to from the redux-saga docs
Cracked it after finding this issue from way back.
The fix is to create a named function to do the select and export it from the module where the saga under test lives, and then use this same function in tests. All is well.
export const selectAppConfig = state => state.appConfig
const getAccountDetails = function * () {
const { url } = yield select(selectAppConfig)
const accountDetails = yield call(apiFetchAccountDetails, url)
}
import {selectAppConfig} from './sagaToTest'
describe('getAccountDetails', () => {
const iterator = getAccountDetails()
it("should yield an Effect 'select(state=> state.appConfig)'", () => {
const effect = iterator.next().value
const expected = select(selectAppConfig)
expect(effect).to.deep.eql(expected)
})