I try to write website in React and that was going fine until now. I totally got stuck.
I have component with list of posts which is working fine. My problem is, that I dont know how to add data from JSON to single post component. I was trying to change geting my JSON data from list articles component to app.js and then passing it down to component with my list posts and to single post component, but then I have error with map() function.
//geting data from JSON and passing it through props down
import React, { useEffect, useState } from "react";
import "./style.css";
import SideBar from "../SideBar";
import MainContent from "../MainContent";
import blogData from "../../assets/data/blog.json";
const MainContainer = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
const post = blogData.data;
setPosts(post);
}, []);
return (
<div className="main-container">
<MainContent posts={posts} />
<SideBar posts={posts} />
</div>
);
};
export default MainContainer;
//mapping through posts
import React from "react";
import "./style.css";
import Post from "../Post";
const MainContent = ({ posts }) => {
return (
<main className="main-content">
{posts.map(post => {
return <Post key={post.id} post={post} />;
})}
</main>
);
};
export default MainContent;
//Post from list of posts
const Post = ({ post }) => {
return (
<div className="post">
<Animated
animationIn="bounceInLeft"
animationOut="fadeOut"
isVisible={true}
>
<h3 className="postTitle">{post.blogTitle}</h3>
<div className="imgContainer">
<img
alt="travel"
src={require("../../assets/img/" + post.blogImage)}
></img>
</div>
<p className="postDescription">{post.blogText}</p>
<NavLink to={`/post/${post.id}`}>
<h5 className="postLink">Read more</h5>
</NavLink>
<h5 className="posteDate">
Posted on {post.postedOn} by {post.author}
</h5>
</Animated>
</div>
);
};
export default Post;
Here is link to my repo:
https://github.com/Gitarrra92/travel-blog/
I think I should have a state in my component with single object of specific id. I just still dont know how to do this. This is my SinglePost component
const SinglePost = ({ match }) => {
const [singlePosts, setSinglePost] = useState({});
useEffect(() => {
const singlePost = blogSingleData.data;
setSinglePost(singlePost);
console.log(singlePost);
}, [match]);
return (
<>
<Socials />
</>
);
};
export default SinglePost;
Related
I am trying to pass the data from my card Component to User Component on a button click.
Both are independent components.
In card component I and fetching data from an API. Now when I click on any User Info Button I want to go on the User Page and want to display its data.
I did try it using react-redux. But I got all elements on the user page. I need only one user on which profile I clicked.
Is there any way to solve this issue with or without redux?
Card.js
import React, { useEffect,useState } from 'react'
import axios from 'axios'
import { NavLink } from 'react-router-dom'
import User from './User'
import { useStateValue } from './Stateprovider'
const Card = ({id,name,Image},props) => {
const [posts, setposts] = useState([])
useEffect(() => {
axios.get('https://s3-ap-southeast-1.amazonaws.com/he-public-data/users49b8675.json')
.then(res =>{
console.log(res);
setposts(res.data)
})
.catch(err =>{
console.log(err);
})
},[])
const [filter,setfilter] = useState('');
const searchText = (event) =>{
setfilter(event.target.value);
}
let dataSearch = posts.filter(item =>{
return Object.keys(item).some(key =>
item[key].toString().toLowerCase().includes(filter.toString().toLowerCase()))
})
function sendData(){
<User id={id} name={name} />
}
return (
<>
<div className="card-area">
{
dataSearch.map((item) => {
let {id,name,Image}=item
return (
<>
<div key="id" className="card">
<img src={Image} alt="" />
<div className="card-data">
<h3><span>User Id: </span>{id}</h3>
<h2><span>Name: </span>{name}</h2>
</div>
<NavLink className="button" exact to={`/${item.id}`} onClick={()=>sendData()}> User Info </NavLink>
</div>
</>
)} )
}
</div>
</>
)
}
export default Card;
User.js
import React, { useState } from 'react'
import { NavLink } from 'react-router-dom';
import { useEffect } from 'react/cjs/react.development';
import Card from './Card';
import { useStateValue } from './Stateprovider';
const User = (props) => {
return (
<>
<div key="id" className="card">
<img src={props.Image} alt="" />
<div className="card-data">
<h3><span>User Id: </span>{props.id}</h3>
<h2><span>Name: </span>{props.name}</h2>
</div>
<NavLink className="button" exact to='/home' > User Info </NavLink>
</div>
</>
)
}
export default User;
I am assuming you have a route for displaying the user info, in that case you can use Link component from react-router to redirect the user to a new page with a predefined state
<Link
to={{
pathname: "/userinfo",
state: { userinfo: {
id: "some id",
name: "some name"
}}
}}
/>
and you can access the state in the userinfo component using props.location.state.userinfo.
also take a look at this thread How do I pass state through React_router? and https://v5.reactrouter.com/web/api/Link
You need to pass props to the component to have access to it
React component and props
So I want to toggle between different categories in my react movie-app such as Trending,Top Rated,Popular etc.I am use useState hook for this,by making the initial state as one category then changing the state through the onClick event on the buttons.But it doesn't seem to be working.What could be the problem?
Code:
App.js
import { useState } from "react";
import Movie from "./components/Movie";
import requests from "./components/ApiRequest";
import Navbar from "./components/Navbar";
function App() {
const [category, setCategory] = useState('top_rated')
return (
<div className="App">
<Navbar setCategory={setCategory} />
<div className="movie-container">
<Movie fetchUrl={"movie/" + category + "?api_key=" + API_KEY + "&language=en-US&page=1"} />
</div>
</div>
);
}
export default App;
Navbar.js
import React from 'react'
import SearchBar from './SearchBar'
import { FiFilter } from 'react-icons/fi'
const Navbar = ({ setCategory }) => {
return (
<div className="navbar-container">
<button className="navbar-btn"><FiFilter />Filter</button>
<div className="categories">
<button className="cat-btn" onClick={() => setCategory("popular")}>Popular</button>
<button className="cat-btn" onClick={() => setCategory("top_rated")}>Top Rated</button>
<button className="cat-btn" onClick={() => setCategory("upcoming")}>Upcoming</button>
</div>
<SearchBar />
</div>
)
}
export default Navbar
Movie.js
const Movie = ({ fetchUrl }) => {
const [movie, setMovie] = useState([]);
useEffect(() => {
async function getPost() {
const response = await client.get(fetchUrl);
console.log(response);
setMovie(response.data.results);
// return response;
}
getPost();
}, [])
return (
movie.map((m) => (
<div className="movie-component" key={m.id}>
<img src={`https://image.tmdb.org/t/p/w500${m.backdrop_path}`} alt="" />
<div className="metadata">
<h1>{m.title}</h1>
<a>⭐{m.vote_average}</a>
</div>
</div>
)
))
}
So I have initialized the useState hook in App.js and then using it in Navbar.js as the set the state of this hook on click event.
useEffect(() => {
async function getPost() {
const response = await client.get(fetchUrl);
console.log(response);
setMovie(response.data.results);
// return response;
}
getPost();
}, [fetchURL])
please update your dependency array as follows.
on changing the category, fetchURL value is being changed.
so it need to be included in dependency array of useEffect Hook.
I tried to make new component for list film. But it seems error in page Home.
Here my code in component list map:
import './Home.css';
import './ListFilm';
import ListFilm from './ListFilm';
function Home() {
return (
<div className="Home">
<h2>The List of Films</h2>
<div className="list film">
<ListFilm/>
</div>
</div>
);
}
export default Home;
Here is component file named ListFilm.js :
import {useState, useEffect} from 'react';
function ListFilm() {
const [post, setPost] = useState({});
useEffect(() => {
const fetchData = async () => {
const response = await fetch(
"https://api.themoviedb.org/3/movie/now_playing?api_key=9e0de5499870264659308848dbad6b2a"
);
const data = await response.json();
setPost(data);
console.log(response)
console.log(data);
};
fetchData();
}, []);
return (
<>
{post.results && post.results.map((item, index) => (
<div key={index}>
<h3>{item.original_title}</h3>
<img src={item.backdrop_path} alt="poster"/>
<p>Tanggal Rilis: {item.release_date}</p>
</div>
))}
</>
);
}
export default ListFilm;
The goal is making data and image in listfilm.js showing in page Home.js. The error code in console log said that index.js:1 The above error occurred in the component: Please help me. Thanks
I was about rounding up this activity and I started getting this error:
Module not found: Can't resolve './components/Post' in ./src/pages/index.js
I have tried all I could but was not able to solve this problem. Below is the list of my codes:
index.js
import React, { useState, useEffect } from 'react';
import Posts from './components/Pagination';
import Pagination from './components/Post';
import axios from 'axios';
const Home = () => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage] = useState(10);
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
const res = await axios.get('https://jsonplaceholder.typicode.com/posts');
setPosts(res.data);
setLoading(false);
};
fetchPosts();
}, []);
// Get current posts
const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);
// Change page
const paginate = pageNumber => setCurrentPage(pageNumber);
return (
<div
style={{
display: 'flex',
height: '90vh'
}}
>
<img src={require('../images/top_img.jpg')} alt='logo' height='500px' width='100%'/>
<div className='container mt-5'>
<h1 className='text-primary mb-3'>LATEST NEWS</h1>
<Posts posts={currentPosts} loading={loading} />
<Pagination
postsPerPage={postsPerPage}
totalPosts={posts.length}
paginate={paginate}
/>
</div>
</div>
);
};
export default Home;
Post.js
import React from 'react';
const Posts = ({ posts, loading }) => {
if (loading) {
return <h2>Loading...</h2>;
}
return (
<ul className='list-group mb-4'>
{posts.map(post => (
<li key={post.id} className='list-group-item'>
{post.title}
</li>
))}
</ul>
);
};
export default Posts;
Pagination.js
import React from 'react';
const Posts = ({ posts, loading }) => {
if (loading) {
return <h2>Loading...</h2>;
}
return (
<ul className='list-group mb-4'>
{posts.map(post => (
<li key={post.id} className='list-group-item'>
{post.title}
</li>
))}
</ul>
);
};
export default Posts;
Below is the structure of my code:
I believe your object names are swapped.
Isn't there an error of relative path?
import Posts from '../components/Pagination';
import Pagination from './components/Post';
both imports are in the same file and both files are in the same folder, but one has ../ and other ./
First, you I would make the named imports match the file structure:
import Post from "./components/Post"
import Pagination from "./components/Pagination"
Also, your default exports are messing things up as well. You will want to export Pagination and then in ./Post you want to export Post.
Lastly, your paths were messed up. The "components" folder is on the same level as index.js. Thus, you can access it through "./components"
I have a mapped list that contains another component that is also mapped.
(https://stackblitz.com/edit/rowmaptest?embed=1&file=LaneInfo.jsx)
What I'm trying to do is toggle a single row to show the data from the subcomponent.
LaneInfo.jsx
import React, { useState, useEffect } from "react";
import data from "./data.js";
import CarContainer from "./CarContainer";
const LaneInfo = () => {
const laneData = data.lanes;
const [showLanes, setShowLanes] = useState(false);
return (
<>
{laneData.map(lane => (
<>
<div className="lane" onClick={() => setShowLanes(!showLanes)}>
<div className="space" key={lane.name}>
<div>{lane.name}</div>
<div>{lane.type}</div>
</div>
</div>
{showLanes && <CarContainer data={lane.cars} />}
</>
))}
</>
);
};
export default LaneInfo;
with the onClick function, the idea is to hide the div that has been clicked.
However, as you can see in my demo when I click the row both items either open or close.
I think that it will require me to get the unique id of the row from Data.js since this is the way I mapped the rows in , but I haven't been able to figure it out yet.
You might be better creating a separate Lane component and have it manage its own state:
import React, { useState, useEffect } from "react";
import data from "./data.js";
import CarContainer from "./CarContainer";
const Lane = ({
lane
}) => {
const [showLane, setShowLane] = useState(false);
return (
<>
<div className="lane" onClick={() => setShowLane(!showLane)}>
<div className="space" key={lane.name}>
<div>{lane.name}</div>
<div>{lane.type}</div>
</div>
</div>
{showLane && <CarContainer data={lane.cars} />}
</>
);
};
const LaneInfo = () => {
const laneData = data.lanes;
return (
<>
{laneData.map(lane => (
<Lane lane={lane} />
))}
</>
);
};
export default LaneInfo;