Sho*_*han 5 reactjs react-router-dom
我正在尝试将 videoTitle 从链接状态传递到我的测验页面。但我无法通过 useLocation 传递它。它向我抛出此错误: TypeError:无法解构“位置”的属性“状态”,因为它未定义。
从这个链接组件:
对此:
这是视频页面的完整代码:
import React, { useState } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';
import { Link } from 'react-router-dom';
import useVideoList from '../hooks/useVideoList';
import classes from '../styles/Videos.module.css';
import Video from './Video';
export default function Videos() {
const [page, setPage] = useState(1);
const { loading, error, videos, hasMore } = useVideoList(page);
return (
<div className={classes.videos}>
{videos.length > 0 && (
<InfiniteScroll
dataLength={videos.length}
next={() => setPage(page + 9)}
hasMore={hasMore}
loader={<h4>Loading...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{videos.map((video) =>
video.noq > 0 ? (
<Link
to={{
pathname: `/quiz/${video.youtubeID}`,
state: {
videoTitle: video.title,
},
}}
key={video.youtubeID}
>
<Video
title={video.title}
id={video.youtubeID}
noq={video.noq}
/>
</Link>
) : (
<Video
title={video.title}
id={video.youtubeID}
noq={video.noq}
key={video.youtubeID}
/>
)
)}
</InfiniteScroll>
)}
{!loading && videos.length === 0 && <div>No data found!</div>}
{error && <div>There was an error!</div>}
{loading && <div>Loading...</div>}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
这是测验页面的完整代码,我想从链接组件传递 videoTitle:
import { getDatabase, ref, set } from 'firebase/database';
import _ from 'lodash';
import React, { useEffect, useReducer, useState } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router';
import { useAuth } from '../../context/AuthContext';
import useQuestions from '../../hooks/useQuestions';
import Answers from '../Answers';
import MiniPlayer from '../MiniPlayer';
import ProgressBar from '../ProgressBar';
const initialState = null;
const reducer = (state, action) => {
switch (action.type) {
case 'questions':
action.value.forEach((question) => {
question.options.forEach((option) => {
option.checked = false;
});
});
return action.value;
case 'answer':
const questions = _.cloneDeep(state);
questions[action.questionID].options[action.optionIndex].checked =
action.value;
return questions;
default:
return state;
}
};
export default function Quiz() {
const { id } = useParams();
const { loading, error, questions } = useQuestions(id);
const [currentQuestion, setCurrentQuestion] = useState(0);
const [qna, dispatch] = useReducer(reducer, initialState);
const navigate = useNavigate();
const { location } = useLocation();
const { state } = location;
const { videoTitle } = state;
const { currentUser } = useAuth();
useEffect(() => {
dispatch({
type: 'questions',
value: questions,
});
}, [questions]);
function handleAnswerChange(e, index) {
dispatch({
type: 'answer',
questionID: currentQuestion,
optionIndex: index,
value: e.target.checked,
});
}
// handle when user hit the next button to get next questions
function nextQuestion() {
if (currentQuestion + 1 < questions.length) {
setCurrentQuestion((prevCurrent) => prevCurrent + 1);
}
}
// handle when user hit the prev button to get the prev questions
function prevQuestion() {
if (currentQuestion >= 1 && currentQuestion <= questions.length) {
setCurrentQuestion((prevCurrent) => prevCurrent - 1);
}
}
// submit quiz
async function submit() {
const { uid } = currentUser;
const db = getDatabase();
const resultRef = ref(db, `result/${uid}`);
await set(resultRef, {
[id]: qna,
});
navigate(`/result/${id}`, {
state: {
qna,
},
});
}
//calculate percentage of progress
const percentage =
questions.length > 0 ? ((currentQuestion + 1) / questions.length) * 100 : 0;
return (
<>
{loading && <div>Loading...</div>}
{error && <div>There was an error!</div>}
{!loading && !error && qna && qna.length > 0 && (
<>
<h1>{qna[currentQuestion].title}</h1>
<h4>Question can have multiple answers</h4>
<Answers
input
options={qna[currentQuestion].options}
handleChange={handleAnswerChange}
/>
<ProgressBar
next={nextQuestion}
prev={prevQuestion}
submit={submit}
progress={percentage}
/>
<MiniPlayer id={id} title={videoTitle} />
</>
)}
</>
);
}
Run Code Online (Sandbox Code Playgroud)
Dre*_*ese 19
在react-router-domv6中Link,组件 API 发生了一些变化,路由状态现在是顶级 prop,而不是嵌套在toprop 的对象中。
Run Code Online (Sandbox Code Playgroud)interface LinkProps extends Omit< React.AnchorHTMLAttributes<HTMLAnchorElement>, "href" > { replace?: boolean; state?: any; to: To; reloadDocument?: boolean; }
将嵌套state属性移出作为链接state道具。
<Link
to={`/quiz/${video.youtubeID}`}
state={{ videoTitle: video.title }} // <-- state prop
key={video.youtubeID}
>
<Video
title={video.title}
id={video.youtubeID}
noq={video.noq}
/>
</Link>
Run Code Online (Sandbox Code Playgroud)
您也没有location正确访问该对象,useLocation挂钩返回一个location对象,而不是具有属性的对象location。
const location = useLocation();
const { state } = location;
Run Code Online (Sandbox Code Playgroud)
或者state直接解构
const { state } = useLocation();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15464 次 |
| 最近记录: |