使用useContext

时间:2019-11-06 19:17:55

标签: reactjs react-router react-hooks react-router-v4 react-router-dom

我已将我的项目移至Codesandbox,以寻求有关问题的更好帮助。这是link to the project.

我有两个组件SearchFormAnimeDetails,它们从我的上下文组件AnimeContext接收API调用。该表单用于显示请求的搜索到的动漫,而AnimeDetails则用于显示所选动漫的详细信息。

我正在使用props.match.paramsTopAnime组件中使用<Link to={} />props.history.push来获取Redirect组件中的动画ID,一旦提交表单, 。

当我尝试单击动漫卡以获取详细信息时,会收到

  

props.match未定义

提交表单时,我看到搜索到的动画出现,但随后收到

  

props.history未定义

我假设这是React Router问题,并且我没有正确设置某些内容。

这是我到目前为止尝试过的,但没有任何效果:

  • 使用useHistory

  • 使用AnimeProvider钩子

  • withRouter包装props.match

简而言之,我无法搜索任何标题,也无法单击主页上的任何动漫标题来获取其详细信息,而不会为props.historySearchForm不确定。

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;

1 个答案:

答案 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);