How to pass JSON data using useNavigation Hooks in React Js? - javascript

This is my Json file which I created in my app.
export const Data = [
{
id: 1,
title: "Tilte 1",
description: "Decription 1 Data",
},
{
id: 2,
title: "Tilte 2",
description: "Decription 2 Data",
}
];
This is my main file from where I navigate it. I use json file to display all the records on page. When I click on selected item it will get its id and navigate to another page, where i can get the data of selected item coming from json.
import React from "react";
import { Data } from "./JSON"
import { useNavigate } from 'react-router-dom'
const Home = () => {
let naviagte = useNavigate();
return (
<>
{Data.map((data, key) => {
return (
<div class="card" >
<div class="card-body">
<h5 class="card-title" key={key.id}>{data.title}</h5>
<p class="card-text">{data.description}</p>
<button onClick={() => naviagte(`/service/${data.id}`)}>{data.title} </button>
</div>
</div>
);
})}
</>
)
}
export default Home;
When I navigate to another page where I want to display all data regarding the selected id. It shows only id not all data.
import React, {useState, useEffect} from "react";
import { Data } from "../home/JSON"
import { useParams } from "react-router-dom";
const Service = () => {
const { id } = useParams();
const [data, setData] =useState('');
console.log("check", data);
useEffect(() => {
setData (Data.map((_data) => _data.id === id ))
}, [id])
return(
<>
{id}
{data.title}
{data.description}
</>
)
}
export default Service;
Please guide me what I miss here. Thanks in Advance

Since you are importing the data in both places you just need to find the data by the id property instead of mapping it to booleans. Keep in mind that your id property is a number but the id route param will be a string, so you will need to convert them to a compatible type for the strict equality (===) check.
Example:
useEffect(() => {
setData(Data.find((_data) => String(_data.id) === id));
}, [id]);
Since data is treated as an object in the render return you'll want to insure you maintain a valid state invariant. Update the initial data state to be an object, and check that Array.prototype.find returned a defined object from the Data array before updating state.
const Service = () => {
const { id } = useParams();
const [data, setData] = useState({});
console.log("check", data);
useEffect(() => {
const data = Data.find((_data) => String(_data.id) === id);
if (data) {
setData(data);
}
}, [id]);
return (
<>
{id}
{data.title}
{data.description}
</>
);
};

Related

Match id betwen URL and list React JS

I'm creating a blog with ReactJS. I have a data component that only contains my data for each articles. I'm able to show all my list of articles on my blog page. The problems comes when I click on an article. I'm able to get the ID in the URL and other params and show it in my article.
The problem: I'd like to not pass all the params into the URL...
I just want to pass ID into the URL, and say to my app:
Get all the values of the row that contain this ID from this data file.
Here the code I tried to fix it (it show a blank page):
import React, { useEffect, useState } from 'react'
import imgBien1 from '../../images/imgBien1.JPG'
import { ColumnSection, Section, SectionInterne, Column2, ContentWrapper2, Img, Column1,ContentWrapper, TopLine, Heading, Subtitle } from './stockUnique'
import {useParams} from 'react-router-dom';
import { posts } from '../Data/data'
const StockUnique = () => {
const { id } = useParams();
const [blog, setBlog] = useState(null);
useEffect(() => {
let blog = posts.find((blog) => blog.id === parseInt(id));
if (blog) {
setBlog(blog);
}
}, []);
return (
<Section >
<ColumnSection>
<SectionInterne>
<Column2>
<ContentWrapper2>
<Img src={imgBien1} alt='ok' />
</ContentWrapper2>
</Column2>
<Column1>
<ContentWrapper>
<TopLine>{id}</TopLine>
<Heading>{blog.title}</Heading>
<Subtitle>{blog.content}</Subtitle>
</ContentWrapper>
</Column1>
</SectionInterne>
</ColumnSection>
</Section>
)
}
export default StockUnique
My data list:
export const posts = [
{ id: 1, title: 'Hello World', content: 'Mon article 1', typeDeBien: "maison" },
{ id: 2, title: 'Bravo', content: 'Mon article2', typeDeBien: "terrain" },
{ id: 3, title: 'Charlie', content: 'Mon article 3', typeDeBien: "appartement" }
];
edit: Navigation code:
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'
import React from 'react'
import StockPage from './pages/stock';
import UniqueStockPage from './pages/unique'
const App = () => {
return (
<Router>
<Routes>
<Route path="/stock" element={<StockPage/>} exact />
<Route
path="/unique/:id"
// path="/unique/:id/:title/:content"
element={<UniqueStockPage/>} exact
/>
</Routes>
</Router>
)
}
export default App;
You might have to check if id has a value
useEffect(() => {
if(id){
let blog = posts.find((blog) => blog.id === parseInt(id));
if (blog) {
setBlog(blog);
}
}
}, [id]);
Given route:
<Route path="/unique/:id" element={<UniqueStockPage />} />
Then the UniqueStockPage has the id value it needs to search the posts array for the matching item.
There's no need for state here, just use the posts array and the id route path param to access the matching element and render directly. Don't forget to handle the case where no matching element is found.
Example:
const StockUnique = () => {
const { id } = useParams();
const blog = posts.find((blog) => String(blog.id) === id);
if (!blog) {
return <div>No Blog Found</div>
}
return (
<Section >
<ColumnSection>
<SectionInterne>
<Column2>
<ContentWrapper2>
<Img src={imgBien1} alt='ok' />
</ContentWrapper2>
</Column2>
<Column1>
<ContentWrapper>
<TopLine>{id}</TopLine>
<Heading>{blog.title}</Heading>
<Subtitle>{blog.content}</Subtitle>
</ContentWrapper>
</Column1>
</SectionInterne>
</ColumnSection>
</Section>
)
}
If you want to avoid searching the posts array each render cycle then use the useMemo hook to memoize the blog value.
Example:
const blog = useMemo(() => {
return posts.find((blog) => String(blog.id) === id);
}, [id]);

How to fetch data before render functionnal component in react js

Here Below my code I would like to retrieve all data before starting the render of my component, is there any way to do that in react ? I guess it's maybe a simple code line but as I'm new in coding I still don't know all react components behavior. Thanks for your answer.
import { useState, useEffect } from "react";
import axios from "axios";
import Cookies from "js-cookie";
// import material ui
import CircularProgress from "#mui/material/CircularProgress";
import Box from "#mui/material/Box";
// import config file
import { SERVER_URL } from "../../configEnv";
const Products = ({ catList }) => {
// catList is data coming from app.js file in format Array[objects...]
console.log("catList ==>", catList);
const [isLoading, setIsLoading] = useState(true);
const [dataSku, setDataSku] = useState([]);
console.log("datasku ==>", dataSku);
const tab = [];
useEffect(() => {
// Based on the catList tab I fetch additionnal data linked with each object of catList array
catList.slice(0, 2).forEach(async (element) => {
const { data } = await axios.post(`${SERVER_URL}/products`, {
product_skus: element.product_skus,
});
// The result I receive from the call is an array of objects that I push inside the Tab variable
tab.push({ name: element.name, content: data });
setDataSku(tab);
console.log("tab ==>", tab);
setIsLoading(false);
});
}, [catList]);
return isLoading ? (
<Box sx={{ display: "flex" }}>
{console.log("there")}
<CircularProgress />
</Box>
) : (
<div className="products-container">
<div>LEFT BAR</div>
<div>
{dataSku.map((elem) => {
return (
<div>
<h2>{elem.name}</h2>
</div>
);
})}
</div>
</div>
);
};
export default Products; ```
#Jessy use your loading state to fetch data once,
In your useEffect, check for loading,
useEffect(() => {
if(loading) {
catList.slice(0, 2).forEach(async (element) => {
const { data } = await axios.post(`${SERVER_URL}/products`, {
product_skus: element.product_skus,
});
tab.push({ name: element.name, content: data });
setDataSku(tab);
console.log("tab ==>", tab);
setIsLoading(false);
});
}
}, [catList]);`
I finally managed to displayed all results by adding this condition on the isLoading
if (tab.length === catList.length) {
setIsLoading(false);
}
Many thanks guys for your insight :)

Can't trigger a search function for movie API project because useState is in a different component

my problem is that I have two different components belonging to my App.js project. It's a movie database where I have a list of movies on the front page and I can search for other movies using the search bar. Since I have the search.js and movie.js ( component where i fetch api data and display), the search.js will not trigger as it cant pinpoint what needs to change. Basically my problem is that on submit, nothing changes.
search.js code:
import { useState } from 'react';
import React from 'react';
// search API used to search through database
const searchUrl = "https://api.themoviedb.org/3/search/movie?api_key=d62e1adb9803081c0be5a74ca826bdbd&query="
const Search = ({ }) => {
const [movies, setMovies] = useState([]);
const [search, setSearch] = useState("");
// Search form that fetches search API and returns results
const submitForm = (e) => {
e.preventDefault();
// API used to search for any movie in the database
fetch(searchUrl + search)
.then(res => res.json())
.then(data => {
setMovies(data.results);
})
setSearch("");}
// user search input
const searchQuery = (e) => {
setSearch(e.target.value)
}
return (
<form onSubmit={submitForm}>
<i class="fas fa-search"></i>
<label className="sr-only" htmlFor="searchMovie">Search for a movie</label>
<input
className="search"
type="search"
placeholder="Search for a movie.."
value={search}
onChange={searchQuery}
/>
</form>
)
}
export default Search;
and my movie.js
import { Link } from 'react-router-dom';
import { useState, useEffect } from "react";
const images = "https://image.tmdb.org/t/p/w500/";
// main API used to display trending page
const apiUrl = `https://api.themoviedb.org/3/movie/now_playing?api_key=d62e1adb9803081c0be5a74ca826bdbd&page=`;
const Movie = ( {
}) => {
const [movies, setMovies] = useState([]);
useEffect(() => {
fetch(apiUrl)
.then((res) => res.json())
.then((data)=> {
setMovies(data.results)
})
}, []);
return (
<section className="movieslist">
{movies.length > 0 ? movies.map((movie) => {
return (
<Link to={`/movie/${movie.id}`}>
<div className="moviePoster">
<img src={movie.poster_path ? `${images}${movie.poster_path}` : "https://www.movienewz.com/img/films/poster-holder.jpg"} alt={movie.title} />
<div className="movieInfo">
<h2>{movie.title}</h2>
<p className="voteStyle">Rating: {movie.voteAverage}</p>
<p className="release">Release Date: {movie.release}</p>
<p className="summary">{movie.overview}</p>
<p className="key">{movie.id}</p>
</div>
</div>
</Link>
);
}): <p class="noResults">No results found. Please try again?</p>}
</section>
)
}
export default Movie;
If I understand the expected behavior correctly, you're trying to update the movies state in movies.js from the search.js.
You are updating two different states of two different components that have no relationship with themselves and that is why nothing is happening on submit.
What you'll need is a parent component (for example home.js) that holds search and movies component as children and holds the movies state. The child components should use and update the parent's movie state.
import Movies from "./movies";
import Search from "./search";
const Home = ()=>{
const [movies, setMovies] = useState([]);
// some other code
return (
<>
<Search onSearh={setMovies} />
<Movies movies={movies} onMovies={setMovies}/>
</>);
}
and your movies.js and search.js should consume these props
import { useState } from 'react';
import React from 'react';
// search API used to search through database
const searchUrl = "https://api.themoviedb.org/3/search/movie?api_key=d62e1adb9803081c0be5a74ca826bdbd&query="
const Search = ({ onSearch }) => {
const [search, setSearch] = useState("");
// Search form that fetches search API and returns results
const submitForm = (e) => {
e.preventDefault();
// API used to search for any movie in the database
fetch(searchUrl + search)
.then(res => res.json())
.then(data => {
onSearch(data.results);
})
setSearch("");}
...
import { Link } from 'react-router-dom';
import { useState, useEffect } from "react";
const images = "https://image.tmdb.org/t/p/w500/";
// main API used to display trending page
const apiUrl = `https://api.themoviedb.org/3/movie/now_playing?api_key=d62e1adb9803081c0be5a74ca826bdbd&page=`;
const Movie = ( {movies, onMovies}) => {
useEffect(() => {
fetch(apiUrl)
.then((res) => res.json())
.then((data)=> {
onMovies(data.results)
})
}, []);
...

show api data to frontend(poll) using reactjs

I want to fetch data from API and show frontend using react but I am getting error from frontend side which is (TypeError: answers.map is not a function ) so how can I solve this error --
MY CODE IS -
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
import { getPolls } from "../helper/coreapicalls";
const MainPoll = () => {
const [polls, setPoll] = useState([]);
const [error, seterror] = useState(false);
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([]);
useEffect(() => {
loadPoll();
}, []);
const loadPoll = () => {
getPolls().then((data) => {
if (data.error) {
seterror(data.error);
} else {
setPoll(data);
console.log(data);
}
});
};
// Handling user vote
// Increments the votes count of answer when the user votes
return (
<div className="">
<div className="container">
<h1 className="blog_heading">Poll's of the Day</h1>
<div className="row">
{polls.reverse().map((poll, index) => (
<div className="col-lg-4 col-12" key={index}>
<Poll question={poll.question} answers={poll.options} />
</div>
))}
</div>
</div>
</div>
);
};
export default MainPoll;
Data which I am getting from API is-
enter image description here
Here I have Question , 3 options how can I show to frontend
Error -enter image description here
The problem is:
field options from the API is an object as I see.
But Poll component trying to interact with it like it is an Array: answers.map(answer => answer.option)
As I see from the doc, data format should be:
[
{ option: 'Yes', votes: 8 },
{ option: 'No', votes: 2 }
]
UPDATE: you can use a similar snippet to transform your data into the required format.
data.map(answer => {
return {
question: answer.question,
answers: Object.keys(answer.options).map(key => {return {option: key, votes: 0}})
}
})

don't understand how can I get pollId from reactjs poll

this is my react code here I am getting react poll using API but when I start working on handalchange For POST API request I need (PollId,userId and answer) I am getting userId through { const userId = isAutheticated() && isAutheticated().user._id; } but I do not understand how can I get PollId from my all polls, please help...!
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
import "../../styles.css";
import { isAutheticated } from "../../auth/helper/index";
import { getPolls, postPoll } from "../helper/coreapicalls";
import { useParams } from "react-router-dom";
const MainPoll = () => {
const userId = isAutheticated() && isAutheticated().user._id;
const pollId = useParams();
const id = pollId._Id;
console.log(id);
const [polls, setPoll] = useState([]);
const [error, seterror] = useState(false);
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([]);
useEffect(() => {
loadPoll();
}, []);
const loadPoll = () => {
getPolls().then((data) => {
if (data.error) {
seterror(data.error);
} else {
setPoll(data);
console.log(data);
}
});
};
// Handling user vote
// Increments the votes count of answer when the user votes
const handalchange = () => {
postPoll();
console.log("hello");
};
return (
<div className="">
<div className="container my-5">
<h1 className="blog_heading my-3">Poll's of the Day</h1>
<div className="row">
{polls.reverse().map((poll, index) => (
<div className="col-lg-4 col-12 poll_border" key={index}>
<Poll
noStorage
question={poll.question}
answers={Object.keys(poll.options).map((key) => {
return {
option: key,
votes: poll.options[key].length,
};
})}
onVote={handalchange}
className="mb-2"
/>
</div>
))}
</div>
</div>
</div>
);
};
export default MainPoll;
my frontend image -
Here I have 5 polls , so I can not get PollId from useParams ...! so how can I get..?
Your component seems to represent list of polls, not any specific poll. So if you have an array of polls instead of one poll, than you have multiple ids instead of the single one.
You can get them by mapping your polls array like that:
const pollIds = polls.map((poll) => poll.id); // or any other prop that stores id

Categories