Hacker Rank clone in React - javascript

I'm making a Hacker rank clone project in React, and so far I tried to get all the New Posts from the API.
Since the API only gives me id's I was just able to map over the piece of state that holds that information. But now I want to get the whole data from every id that I got , and then display all the posts. It's been really confusing for me, and i really need some help. Well, to resume everything: I got the id's from a api call and stored it in my state. Now I want to get all of the id's and make another request, but this time I'll get the info based on that specific Id. Here's the code:
import React, { useState } from "react";
import "./styles.css";
import TopList from "./components/TopList";
export default function App() {
const [state, setState] = useState({
data: [23251319, 23251742, 23251158],
results: []
});
const fetcher = id => {
fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`)
.then(res => res.json())
.then(data => {
console.log(data);
setState({
results: data
});
});
};
return (
<div>
<TopList data={state.data} fetcher={fetcher} />
</div>
);
}
import React from "react";
import Top from "./Top";
function TopList({ data, fetcher }) {
const mapped = data.map(item => (
<Top fetcher={fetcher} id={item} key={item} />
));
return <div>{mapped}</div>;
}
export default TopList;
import React from "react";
function Top({ id, fetcher }) {
fetcher(id);
return (
<div>
<h1>Hello from top</h1>
</div>
);
}
export default Top;

As I told you in the comments, the fetcher() function already gets the data of each item using the IDs you have from the first request. I think that a good place to call this function is the TopStoryComponent, as there will be an instance of this component for each ID in the list.
import React from "react";
function TopStoryComponent({ identification, fetcher }) {
// this will print the data to the console
fetcher(identification);
return <div>{identification}</div>;
}
export default TopStoryComponent;
Let me know if it helps you get what you need!

Related

Store fetch data in a variable and use entire json as a prop in a react component

i have the next code, the app should get a json from an api and then pass the entire json as a prop so it can be treated in each component file and return the element to the screen.
The thing is i haven't found a way to just store the info from the fetch into a variable. if i just pass a json that is declared in the same file it would work just fine but can't make it work with the info from the fetch, the developer tools shows the json is being retrieved but it doesn't seem to accesed in the components, as you can see in the components part i tried to use globalData to use the json store in that variable but it breaks my app and the console says "Uncaught TypeError: Cannot read properties of undefined (reading 'name')" in which name is is the first element inside my json.
import logo from './logo.svg';
import './App.css';
import React, {useEffect, useState} from 'react';
import Title from "./components/Title"
import Summary from "./components/Summary"
import Skills from './components/Skills';
import Experience from './components/Experience';
import Sideprojects from './components/Sideprojects';
import Education from './components/Education';
import Interests from './components/Interests';
import Courses from './components/Courses';
import Picture from './components/Picture';
import ReactDOM from "react-dom";
var cvdata = here i have a json with a lot of info, if i just write props = {cvdata} it would work just fine
function App() {
// fetch('http://localhost:5000/api')
// .then(res => console.log(res))
let dataGlobal;
const getData = async () => {
const response = await fetch("http://localhost:5000/api");
const data = await response.json();
dataGlobal = data;
return data;
};
(async () => {
await getData();
console.log(dataGlobal);
})();
return(
<div className="App">
<div className='Upleft'>
<Title props = {dataGlobal}/>
<Summary props = {cvdata}/>
<Experience props = {cvdata}/>
<Education props = {cvdata}/>
</div>
<div className='Right'>
<Picture props = {cvdata}/>
<Skills props = {cvdata}/>
<Interests props = {cvdata}/>
<Courses props = {cvdata}/>
<Sideprojects props = {cvdata}/>
</div>
</div>
)
}
export default App;
Maybe something like this would help:
It can look kinda funky, but essentially the hook useEffect takes an array of states, which when change, fires the containing function. I pass an empty array as the second argument of useEffect to have the fetch for data only happen the first load of the component. The first argument is the function you want to fire, which MUST return undefined. async functions always return a promise, so to work around this, we instead nest an anonymous async function we call immediately so the async / await syntax is available to us.
hopefully the code example is clear enough. If you have any questions or I misunderstood your prompt, please let me know. Good luck! 👍👍
const { useState, useEffect } = React;
function App (props) {
const [ page, setPage ] = useState("loading");
useEffect(() => {(async () => {
const res = await fetch(someWebsite)
.catch(err => setPage(err.message));
if (!res) return;
const txt = await res.text();
setPage(txt);
})();}, []);
return (
<div>
This is the page: <br />
{ page }
</div>
);
}

How to solve this: TypeError: Cannot destructure property 'title' of 'collections' as it is undefined

This is the data that I fetched from firestore and I want to use it in my application to show the product details but I can't retrieve it into my application. Example, I want the data from shop->collections->bags->items to show the specific product details.
And here is my code in product-details.component.jsx:
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { fetchCollectionsStart } from '../../redux/shop/shop.actions'
const ProductDetailsPage = ({ fetchCollectionsStart, match, collections }) => {
const {title, items} = collections;
useEffect(() => {
fetchCollectionsStart();
}, [fetchCollectionsStart]);
console.log(match);
const ShowProduct = () => {
return (
<div>
{title}
</div>
)
}
return (
<div className='product-details'>
<div className="row">
<ShowProduct />
</div>
</div>
);
};
const mapDispatchToProps = dispatch => ({
fetchCollectionsStart: () => dispatch(fetchCollectionsStart())
});
export default connect(null, mapDispatchToProps)(ProductDetailsPage);
The error pop up is shown as the image below:
I don't know why I can't destructure the data from collections. I thought I already successfully fetched it into my application?
Thanks a lot for helping me!!
You need to destructure bags and then get the title from bags.
const { bags } = collections;
console.log(bags.title)
If you dont know whats in collections - you can use Object.keys() to get the different object keys- bags, boys, girls, hats etc.

React JS not able to display firebase data in jsx element

I'm fairly new to React JS and I've been working on one project where I need to first get data from the firebase firestore db and then display it on the page by creating new elements. I need to accomplish this without the whole page refreshing and only the rendered elements being displayed. I have fetched the data from the db and have put it into an array, after that I was trying to use the map function to go through the array and return an h1 element containing the data but it was not showing up on the page. I did a console.log on the data and it's showing up in the console as expected. My main question is, how do I return an h1 elements using the map function that will contain the data from the array?
import React, {useRef} from "react";
import {useHistory} from 'react-router-dom';
import '../connectApp.css';
import Navbar from './Navbar.js';
import SideBar from './sideBar.js';
import {db} from '../fbConfig';
import {auth} from '../fbConfig';
import ReactDOM from 'react-dom'
const App = () => {
const history = useHistory();
const data = [];
if(localStorage.getItem("isAuth") === 'null') { //NOTE - we are only able to store strings in localStorage
history.push('/');
}
var docRef = db.collection("posts");
docRef.onSnapshot(snapshot => {
let changes = snapshot.docChanges();
console.log(changes);
changes.forEach(change => {
if(change.type == "added") {
data.push({
imageUploader:change.doc.data().imageUploader,
imageCaption:change.doc.data().imageCaption,
imageUrl:change.doc.data().imageUrl
})
}
})
return <div>
{data.map(data => {
console.log(data)
})}
</div>
})
return (
<div className="container">
<Navbar />
<SideBar />
</div>
);
}
export default App
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I found that by using the this.state method I was able to set a state for my data, store my data in an array, update the state, and then use the map function as was done previously to get the data and display it in a div.

I'm trying to fetch data from a server using useEffect react hook

I'm trying to fetch data from a server using the fetch api and displaying this data in an unordered list using uuidv4 as the key, im trying to do this using react's useEffect hook, however, it fetches the data but then it says all my keys are the same, i think useEffect is the cause and i tried adding as the second argument an empty array to prevent the rerendering but then its saying im missing a dependency and when i put the dependency in it rerenders and the uuid's are the same again. i'm not sure what to do im relatively new to hooks.
import React, { useState, useEffect } from "react";
import "./App.css";
const uuidv4 = require("uuid/v4");
function App() {
const [country, setCountry] = useState({
country: []
});
useEffect(() => {
console.log("fetching data");
fetch("http://localhost:5000/country")
.then(res => res.json())
.then(data => setCountry({...country, country: data }));
}, []);
return (
<>
<ul>
{country.country.map(item => {
return <li key={uuidv4}>{item.name}</li>;
})}
</ul>
</>
);
}
export default App;
I think you have to call it to generate the uuid:
return <li key={uuidv4()}>{item.name}</li>;
Best way to assign or set the keys when you map over a list is to use index, which you can get from map
return (
<>
<ul>
{country.country.map((item, index) => {
return <li key={index}>{item.name}</li>;
})}
</ul>
</>
);

How can I edit or manipulate the data I get in my state before rendering the data

I am building an app using react and redux
After navigating to a new url an API call is made and the data now exists in the containers state.
What I want to do is before using that API data in a child component (FixtureList). I want to refactor the data. Where do I do that and how do I do that? Below is an example of the data:
Data Example - Please Click Here
From the Data example you can see that we have a key called matchday. I want to group all the objects by the matchday they are in and then render to the front end.
React Container
import React, { Component } from 'react';
import { connect } from 'react-redux';
import FixtureList from '../components/league-fixture-list';
class LeagueFixtures extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div className="row">
<div className="col-xs-12">
<h2>Fixtures</h2>
</div>
</div>
<div className="row">
{this.props.leagueFixtures.fixtures.map((fixture, index) => {
return <FixtureList fixture={fixture} matchday={fixture.matchday} key={index}/>
})}
</div>
</div>
)
}
}
const mapStateToProps = (state) => ({
leagueFixtures: state.LeagueFixtures
})
const mapDispatchToProps = (dispatch) => {
return {
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(LeagueFixtures)
React Component
import React from 'react'
const FixtureList = (props) => {
return (
<div className="col-sm-4">
<li className="list-group-item">
{props.matchday}
{props.fixture.homeTeamName} vs {props.fixture.awayTeamName}
</li>
<p></p>
</div>
);
}
export default FixtureList;
At the moment I loop through all of the data in the container and print it out in my component. It works as expected but I would like to mutate the data so I can achieve a different result.
Thank you
you can use reselect. Basically what you are trying to get is derived data, which can be computed from the original data returned from the server.
Reselect makes it really easy plus it caches the result, so as long as the original data does not change, the derived data is not recomputed (currently it does so in every render).
A possible implementation would be something like this: (using lodash for simplicity)
import { createSelector } from 'reselect';
import { keyBy } from 'lodash';
const fixtures = state => state.LeagueFixtures
const fixturesByMatchDaySelector = createSelector(
fixtures,
(fixtures) => keyBy(fixtures, ({matchday}) => matchday),
)
const mapStateToProps = (state) => ({
leagueFixtures: state.LeagueFixtures,
fixturesByMatchDay: fixturesByMatchDaySelector(state)
})
Hope that helps [=

Categories