#reactjs #react-router #fetch
Вопрос:
@edit ок, поэтому я обновляю свой код в главном приложении:
function App() {
return (
<Layout>
<Switch>
<Route path='/' exact={true}>
<Posts />
</Route>
<Route path='/favorite-posts'>
<FavoritePosts />
</Route>
<Route path='/single-post:id'>
<SinglePost />
</Route>
<Route>
<Page404 path='*' />
</Route>
</Switch>
</Layout>
)
}
Похоже, страницы работают, но как я могу передать заголовок и текст из выборки на одну страницу?
const Posts = () => {
const [data, setData] = useState([])
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
fetchData()
}, [])
// useEffect(() => {
// fetchImg()
// }, [])
const fetchData = async () => {
let response = await fetch('https://jsonplaceholder.typicode.com/posts')
await response
.json()
.then((finish) => {
setIsLoading(false)
setData(finish) //.splice(0, 5)
console.log(finish)
})
.catch((error) => {
console.error('Houston, we have a problem.. with fetch')
})
}
//loading animation
if (isLoading) {
return <Loading />
}
return (
<>
<BlogPosts datas={data} />
</>
)
}
export default Posts
const Post = ({ title, body, random, id }) => {
const favoritesCtx = useContext(FavoritesContext)
const itemIsFavorite = favoritesCtx.itemIsFavorite(id)
function toggleFavoriteStatusHandler() {
if (itemIsFavorite) {
favoritesCtx.removeFavorite(id)
} else {
favoritesCtx.addFavorite({
id: id,
title: title,
body: body,
})
}
}
return (
<article className={styles.box}>
<Link to={`/single-post:${id}`}>
<img
className={styles.box__image}
// src={`https://rickandmortyapi.com/api/character/avatar/${random}.jpeg`}
src={`https://rickandmortyapi.com/api/character/avatar/19.jpeg`}
alt='test'
/>
</Link>
<button
className={itemIsFavorite ? styles.box__btn_two : styles.box__btn}
onClick={toggleFavoriteStatusHandler}
>
{itemIsFavorite ? 'Remove from Favorites' : 'Add to Favorites'}
</button>
<h4 className={styles.box__title}>{title}</h4>
</article>
)
}
const SinglePost = ({ title, body, id }) => {
return (
<section>
<p>{id}</p>
<h1>{title}</h1>
<h2>{body}</h2>
<p>hey</p>
</section>
)
}
export default SinglePost
Я получаю и сопоставляю сообщения с https://jsonplaceholder.typicode.com/posts
У меня уже есть сообщения на моем сайте, но как я могу перейти к одному сообщению и получить уникальную информацию, я имею в виду текст и заголовок по идентификатору сообщения?
Есть идеи, как я могу это сделать?
Комментарии:
1. Что вы имеете в виду под «как я могу перейти на один пост и получить уникальную информацию», можете ли вы уточнить?
2. используйте параметр Url для передачи идентификатора вашего маршрута, например ‘/:postID’ reactrouter.com/web/example/url-params
Ответ №1:
Для этого вам нужно внести несколько изменений. Если вы хотите иметь специальную страницу для каждого поста, то SinglePost
будете действовать как страница. Вам нужно будет добавить маршрут, который принимает идентификатор записи в качестве параметра и на основе этого извлекает данные для этой конкретной записи и отображает этот компонент. Что-то вроде этого:
<Switch>
//...
<Route path='/post/:id'>
<SinglePost />
</Route>
//...
</Switch>
Теперь в SinglePost
файле получите идентификатор из параметра маршрута и выполните вызов api.
import {useParams, useState, useEffect} from 'react'
const SinglePost = (props) => {
//this is where we will store data after getting from api
const [post, setPost] = useState();
// get id from route param using this hook
const id = useParams().id;
// then in useEffect call the api to fetch data for single post
useEffect(()=>{
axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`).then(res => {
setPost(res.data);
})
},[])
return (
<section>
<h1>{post?.title}</h1>
<h2>{post?.body}</h2>
</section>
)
}
export default SinglePost;
Надеюсь, вы поймете картину.
Ответ №2:
Хорошо, я сделал это !
import { useLocation } from 'react-router'
import { useEffect, useState } from 'react'
import styles from './SinglePost.module.css'
import Loading from '../ui/Loading'
import Comments from './Comments'
const SinglePost = () => {
const location = useLocation()
const path = location.pathname.split('/')[2]
const [data, setData] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [comm, setComm] = useState([])
useEffect(() => {
fetchData()
}, [])
useEffect(() => {
fetchComment()
}, [])
const fetchData = async () => {
let response = await fetch(
'https://jsonplaceholder.typicode.com/posts/' path
)
await response.json().then((finish) => {
setIsLoading(false)
setData(finish)
console.log(finish)
})
}
const fetchComment = async () => {
let response = await fetch('https://jsonplaceholder.typicode.com/comments/')
await response.json().then((finish) => {
setIsLoading(false)
setComm(finish.splice(0, 7)) //random
console.log(finish)
})
}
if (isLoading) {
return <Loading />
}
return (
<section className={styles.single}>
<div className={styles.single__text}>
<h1>{data.title}</h1>
<p>{data.body}</p>
<h4>Comments:</h4>
</div>
<div className={styles.comments}>
{comm.map((comme) => {
return (
<Comments
key={comme.id}
name={comme.name}
email={comme.email}
body={comme.body}
/>
)
})}
</div>
</section>
)
}
export default SinglePost
Ответ №3:
Добавьте это в свой маршрут
<Route path='/post:id'>
<Post />
</Route>
И добавьте ссылку на свой компонент публикации для перенаправления
<Link to={"/post" {item._id}/>