我已将我的项目移至Codesandbox,以寻求有关问题的更好帮助。这是link to the project.
我有两个组件SearchForm
和AnimeDetails
,它们从我的上下文组件AnimeContext
接收API调用。该表单用于显示请求的搜索到的动漫,而AnimeDetails
则用于显示所选动漫的详细信息。
我正在使用props.match.params
在TopAnime
组件中使用<Link to={} />
和props.history.push
来获取Redirect
组件中的动画ID,一旦提交表单, 。
当我尝试单击动漫卡以获取详细信息时,会收到
props.match未定义
提交表单时,我看到搜索到的动画出现,但随后收到
props.history未定义
我假设这是React Router问题,并且我没有正确设置某些内容。
这是我到目前为止尝试过的,但没有任何效果:
使用useHistory
使用AnimeProvider
钩子
用withRouter
包装props.match
简而言之,我无法搜索任何标题,也无法单击主页上的任何动漫标题来获取其详细信息,而不会为props.history
和SearchForm
不确定。
import React, { useContext } from 'react';
import { withRouter } from 'react-router-dom'
import styled from 'styled-components'
import AnimeCard from './AnimeCard/AnimeCard';
import { AnimeContext } from '../store/AnimeContext'
const SearchForm = () => {
const { dataItems, animeSearched, handleSubmit } = useContext(AnimeContext)
return (
<div>
<Form onSubmit={handleSubmit}>
<Input
type="text"
name="anime"
placeholder="Enter title"
// ref={value => myValue = value}
/>
<FormButton type='submit'>Search</FormButton>
</ Form>
{animeSearched
?
<AnimeCard />
: null}
</div>
)
}
export default withRouter(SearchForm)
组件
AnimeDetails
import React, { useContext, useEffect } from "react";
import styled from "styled-components";
import { AnimeContext } from "../store/AnimeContext";
const AnimeDetails = () => {
const { fetching, anime, fetchAnimeDetails } = useContext(AnimeContext);
useEffect(() => {
fetchAnimeDetails();
});
return (
<>
{fetching && "Fetching..."}
{anime && (
<AnimeDetailsWrapper>
<AnimeDetailsContainer>
<Poster src={anime.image_url} />
{/* Details */}
<Details>
<Title>{anime.title}</Title>
<TitleJpn>{anime.title_japanese}</TitleJpn>
<Score>{anime.score || "N/A"}</Score>
{/* If no score then display N/A */}
<SongList>
<h3>Opening Themes</h3>
{anime.opening_themes // Make sure data is fully loaded before component renders
? anime.opening_themes.map((song, index) => (
<li key={index}>{song}</li>
))
: null}
</SongList>
</Details>
{/* Info Bar */}
<InfoBar>
{
<li>
Epiosdes: <span className="info-span">{anime.episodes}</span>
</li>
}
{
<li>
Duration: <span className="info-span">{anime.duration}</span>
</li>
}
{
<li>
<a
href={anime.trailer_url}
rel="external noopener noreferrer"
target="_blank"
>
View Trailer
</a>
</li>
}
</InfoBar>
{/* Synopsis */}
<Synopsis>{anime.synopsis}</Synopsis>
</AnimeDetailsContainer>
</AnimeDetailsWrapper>
)}
</>
);
};
export default AnimeDetails;
组件
AnimeContext
import React, { useState, useEffect, createContext } from 'react'
const AnimeContext = createContext()
const API = "https://api.jikan.moe/v3"
const AnimeProvider = (props) => {
const urls = [
`${API}/top/anime/1/airing`,
`${API}/top/anime/1/tv`,
`${API}/top/anime/1/upcoming`,
]
// State for top Anime
const [topTv, setTopTv] = useState([])
const [topAiring, setTopAiring] = useState([])
const [topUpcoming, setTopUpcoming] = useState([])
// State for Anime details
const [animeReq, setAnimeReq] = useState({
fetching: false,
anime: []
})
// State for Anime search form
const [dataItems, setDataItems] = useState([])
const [animeSearched, setAnimeSearched] = useState(false)
// Fetch top Anime
const fetchTopAnime = async () => {
return Promise.all(
urls.map(async url => {
return await fetch(url); // fetch data from urls
})
)
.then((responses) => Promise.all(responses.map(resp => resp.json())) // turn data into JSON
.then(data => {
const topTvFiltered = data[0].top.filter(item => item.rank <= 5) // filter out top 6
const topAiringFiltered = data[1].top.filter(item => item.rank <= 5)
const topUpcomingFiltered = data[2].top.filter(item => item.rank <= 5)
setTopTv(topTvFiltered)
setTopAiring(topAiringFiltered)
setTopUpcoming(topUpcomingFiltered)
console.log(data)
})
)
.catch(err => console.log("There was an error:" + err))
}
useEffect(() => {
fetchTopAnime()
}, [])
// Fetch Anime details
const fetchAnimeDetails = async () => {
setAnimeReq({ fetching: true })
const response = await fetch(`${API}/${props.match.params.animeId}`)
const data = await response.json()
console.log(data);
setAnimeReq({ fetching: false, anime: data }) // set initial state to hold data from our API call
}
const { fetching, anime } = animeReq;
// Fetch searched Anime
async function handleSubmit(e) {
e.preventDefault()
const animeQuery = e.target.elements.anime.value
const response = await fetch(`${API}/search/anime?q=${animeQuery}&page=1`)
const animeData = await response.json()
setDataItems(animeData.results)
setAnimeSearched(!animeSearched)
props.history.push('/dashboard')
}
return (
<AnimeContext.Provider value={{
topTv,
setTopTv,
topAiring,
setTopAiring,
topUpcoming,
setTopUpcoming,
dataItems,
setDataItems,
animeSearched,
setAnimeSearched,
fetching,
anime,
fetchTopAnime,
fetchAnimeDetails,
handleSubmit
}}>
{props.children}
</AnimeContext.Provider>
)
}
export { AnimeProvider, AnimeContext }
组件
if Sender.DataController.GetValue(AViewInfo.GridRecord.RecordIndex, 15) = 1 then
begin
ACanvas.Font.Color := clRed;
end;
答案 0 :(得分:0)
您应该这样做
import { useLocation, useNavigate } from 'react-router-dom';
//You should navigate
const navigate = useNavigate();
navigate('/app/example', { state: { message: "hello" } });
//You can receive
const location = useLocation();
console.log("location data", location.state);