sar*_*rah 6 javascript reactjs react-router
我需要有关此问题的帮助,我的应用程序组件如下图所示。我想在单击“查看详细信息”按钮时inselectedTrack使用的状态存储跟踪对象。useState然后用它来显示轨道详细信息,而不是从 API 中再次获取来获取轨道详细信息,但是当我useContext在内部使用时,会出现此错误TypeError: Cannot read property 'selectedTrack' of undefined。
反应组件
import React from 'react';
import Header from './Header';
import Search from '../tracks/Search';
import Tracks from '../tracks/Tracks';
import Footer from './Footer';
import TrackContextProvider from '../../contexts/TrackContext';
const Main = () => {
return (
<div>
<TrackContextProvider>
<Header />
<Search />
<Tracks />
<Footer />
</TrackContextProvider>
</div>
);
};
export default Main;
Run Code Online (Sandbox Code Playgroud)
TrackContext.js
import React, { createContext, useState, useEffect } from 'react';
export const TrackContext = createContext();
const TrackContextProvider = props => {
const [tracks, setTracks] = useState([]);
const [selectedTrack, setSelectedTrack] = useState([{}]);
const API_KEY = process.env.REACT_APP_MUSICXMATCH_KEY;
useEffect(() => {
fetch(
`https://cors-anywhere.herokuapp.com/https://api.musixmatch.com/ws/1.1/chart.tracks.get?chart_name=top&page=1&page_size=10&country=fr&f_has_lyrics=1&apikey=${API_KEY}`
)
.then(response => response.json())
.then(data => setTracks(data.message.body.track_list))
.catch(err => console.log(err));
// to disable the warning rule of missing dependency
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// state for heading
const [heading, setHeading] = useState(['Top 10 Tracks']);
return (
<TrackContext.Provider value={{ tracks, heading, selectedTrack, setSelectedTrack }}>
{props.children}
</TrackContext.Provider>
);
};
export default TrackContextProvider;
Run Code Online (Sandbox Code Playgroud)
import React, { Fragment, useContext } from 'react';
import { Link } from 'react-router-dom';
import { TrackContext } from '../../contexts/TrackContext';
const TrackDetails = () => {
const { selectedTrack } = useContext(TrackContext);
console.log(selectedTrack);
return (
<Fragment>
<Link to="/">
<button>Go Back</button>
</Link>
<div>
{selectedTrack === undefined ? (
<p>loading ...</p>
) : (
<h3>
{selectedTrack.track.track_name} by {selectedTrack.track.artist_name}
</h3>
)}
<p>lyrics.............</p>
<div>Album Id: </div>)
</div>
</Fragment>
);
};
export default TrackDetails;
Run Code Online (Sandbox Code Playgroud)
import React, { useState, useContext, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { TrackContext } from '../../contexts/TrackContext';
const Track = ({ trackInfo }) => {
const { selectedTrack, setSelectedTrack } = useContext(TrackContext);
const handleClick = e => {
setSelectedTrack(trackInfo);
};
console.log(selectedTrack);
return (
<li>
<div>{trackInfo.track.artist_name}</div>
<div>Track: {trackInfo.track.track_name}</div>
<div>Album:{trackInfo.track.album_name}</div>
<div>Rating:{trackInfo.track.track_rating}</div>
<Link to={{ pathname: `/trackdetails/${trackInfo.track.track_id}`, param1: selectedTrack }}>
<button onClick={handleClick}>> View Lyric</button>
</Link>
</li>
);
};
export default Track;
Run Code Online (Sandbox Code Playgroud)
更新:添加轨道组件
import React, { useContext, Fragment } from 'react';
import Track from './Track';
import { TrackContext } from '../../contexts/TrackContext';
const Tracks = () => {
const { heading, tracks } = useContext(TrackContext);
const tracksList = tracks.map(trackInfo => {
return <Track trackInfo={trackInfo} key={trackInfo.track.track_id} />;
});
return (
<Fragment>
<p>{heading}</p>
{tracks.length ? <ul>{tracksList}</ul> : <p>loading...</p>}
</Fragment>
);
};
export default Tracks;
Run Code Online (Sandbox Code Playgroud)
我认为这里的问题是,由于selectedTrack是异步加载的,当从上下文访问它时,它是未定义的(您可以通过在调用中传递默认值来绕过TrackContext它)。由于 selectedTrack 变量是随时填充的,因此您应该将其存储在with挂钩中,并将该引用作为上下文值的一部分返回。这样您就可以从该上下文的任何消费者那里获得最新的价值。undefinedcreateContextRefuseRefselectedTrack
const selectedTracks = useRef([]);
useEffect(() => {
fetch(
`https://cors-anywhere.herokuapp.com/https://api.musixmatch.com/ws/1.1/chart.tracks.get?chart_name=top&page=1&page_size=10&country=fr&f_has_lyrics=1&apikey=${API_KEY}`
)
.then(response => response.json())
.then(data => {
selectedTrack.current = data.message.body.track_list;
})
.catch(err => console.log(err));
// to disable the warning rule of missing dependency
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
44952 次 |
| 最近记录: |