Javascript 使用react router dom的history.push()在某些组件中有效,但在其他组件中无效
正如标题所说。我正在使用React router dom,因此在我的App.js文件中,我设置了包含交换机和多条路由的路由器。通过几个较小的组件,我可以使用Usehistory和history.push()来操纵历史记录并导航我的应用程序 但是在我的App.js文件中,它不起作用,我得到了返回: “TypeError:无法读取未定义的属性'push'” 我不知道是什么问题,任何帮助都会非常感激Javascript 使用react router dom的history.push()在某些组件中有效,但在其他组件中无效,javascript,reactjs,react-router,react-hooks,Javascript,Reactjs,React Router,React Hooks,正如标题所说。我正在使用React router dom,因此在我的App.js文件中,我设置了包含交换机和多条路由的路由器。通过几个较小的组件,我可以使用Usehistory和history.push()来操纵历史记录并导航我的应用程序 但是在我的App.js文件中,它不起作用,我得到了返回: “TypeError:无法读取未定义的属性'push'” 我不知道是什么问题,任何帮助都会非常感激 import React, { useState, useEffect } from "re
import React, { useState, useEffect } from "react";
import {
BrowserRouter as Router,
Route,
Switch,
useHistory,
} from "react-router-dom";
import styled from "styled-components";
import unsplash from "../api/unsplash";
import Header from "./Header";
import Customise from "./Customise";
import LandingPage from "./LandingPage";
import GameBoard from "./GameBoard";
import GameFinished from "./GameFinished";
function App() {
const [searchImageTerm, setSearchImageTerm] = useState("south africa");
const [images, setImages] = useState([]);
const [randomisedImages, setRandomisedImages] = useState([]);
const [roundStarted, setRoundStarted] = useState(false);
const [firstSelectedTile, setFirstSelectedTile] = useState(null);
const [secondSelectedTile, setSecondSelectedTile] = useState(null);
const [matchedTiles, setMatchedTiles] = useState([]);
const [endOfTurn, setEndOfTurn] = useState(false);
const [score, setScore] = useState(0);
const [minutes, setMinutes] = useState(2);
const [seconds, setSeconds] = useState(0);
const [difficulty, setDifficulty] = useState(8);
const history = useHistory();
useEffect(() => {
getImages();
}, [searchImageTerm, difficulty]);
useEffect(() => {
randomiseImagesWithID(images);
}, [images]);
useEffect(() => {
if (minutes === 0 && seconds === 0) {
finishGame();
}
}, [seconds, minutes]);
const finishGame = () => {
history.push(`/gamefinished`);
};
useEffect(() => {
if (roundStarted) {
let myInterval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(myInterval);
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000);
return () => {
clearInterval(myInterval);
};
}
});
useEffect(() => {
if (matchedTiles.length > 0 && matchedTiles.length === images.length / 2) {
alert("YOU WON!");
}
}, [matchedTiles]);
const getImages = async () => {
const response = await unsplash.get("/search/photos", {
params: { query: searchImageTerm, per_page: difficulty },
});
setImages(response.data.results);
};
const generateTileId = () => {
return "tile_id_" + Math.random().toString().substr(2, 8);
};
const randomiseImagesWithID = (images) => {
let duplicateImagesArray = [...images, ...images];
var m = duplicateImagesArray.length,
t,
i;
while (m) {
i = Math.floor(Math.random() * m--);
t = duplicateImagesArray[m];
duplicateImagesArray[m] = duplicateImagesArray[i];
duplicateImagesArray[i] = t;
}
let finalArray = [];
for (let image of duplicateImagesArray) {
finalArray.push({
...image,
tileId: generateTileId(),
});
}
setRandomisedImages([...finalArray]);
};
const startRound = () => {
setRoundStarted(true);
};
const onTileClick = (tileId, id) => {
// is the tile already paired && is the tile selected && is it the end of the turn?
if (
!matchedTiles.includes(id) &&
tileId !== firstSelectedTile &&
!endOfTurn
) {
// find image id for first selcted id for comparrison
const firstSelctedTileId = randomisedImages.find(
(image) => image.tileId === firstSelectedTile
)?.id;
// if there is no selected tile set first selected tile
if (!firstSelectedTile) {
setFirstSelectedTile(tileId);
} else {
// if the second tile matches the first tile set matched tiles to include
if (id === firstSelctedTileId) {
setMatchedTiles([...matchedTiles, id]);
// add points to score
setScore(score + 6);
// reset selected tiles
setFirstSelectedTile(null);
} else {
// deduct points from score
setScore(score - 2);
// set and display second tile choice
setSecondSelectedTile(tileId);
// set end of turn so tiles cannot be continued to be selected
setEndOfTurn(true);
// reset all values after a few seconds
setTimeout(() => {
setFirstSelectedTile(null);
setSecondSelectedTile(null);
setEndOfTurn(false);
}, 1500);
}
}
}
};
const onResetClick = () => {
randomiseImagesWithID(images);
setFirstSelectedTile(null);
setSecondSelectedTile(null);
setMatchedTiles([]);
setScore(0);
setEndOfTurn(false);
};
return (
<div>
<Router>
<Container>
<Header
onResetClick={onResetClick}
score={score}
seconds={seconds}
minutes={minutes}
/>
<Main>
<Switch>
<Route path="/gameboard">
<GameBoard
images={randomisedImages}
onTileClick={onTileClick}
firstSelectedTile={firstSelectedTile}
secondSelectedTile={secondSelectedTile}
matchedTiles={matchedTiles}
/>
</Route>
<Route path="/customise">
<Customise
setSearchImageTerm={setSearchImageTerm}
setDifficulty={setDifficulty}
setMinutes={setMinutes}
startRound={startRound}
/>
</Route>
<Route path="/gamefinished">
<GameFinished />
</Route>
<Route path="/">
<LandingPage startRound={startRound} />
</Route>
</Switch>
</Main>
</Container>
</Router>
</div>
);
}
export default App;
const Container = styled.div`
width: 100%;
height: 100vh;
display: grid;
grid-template-rows: 7rem;
`;
const Main = styled.div`
display: grid;
grid-template-columns: auto;
`;
import React,{useState,useffect}来自“React”;
进口{
BrowserRouter作为路由器,
路线,,
转换
使用历史,
}从“反应路由器dom”;
从“样式化组件”导入样式化;
从“./api/unsplash”导入unsplash;
从“/Header”导入标题;
从“/Customise”导入自定义;
从“/LandingPage”导入LandingPage;
从“/GameBoard”导入GameBoard;
从“/GameFinished”导入GameFinished;
函数App(){
const[searchImageTerm,setSearchImageTerm]=useState(“南非”);
const[images,setImages]=useState([]);
const[randomisedImages,setRandomisedImages]=useState([]);
const[roundStarted,setRoundStarted]=useState(false);
常量[FirstSelectedFile,SetFirstSelectedFile]=useState(null);
常量[SecondSelectedFile,SetSecondSelectedFile]=useState(null);
const[matchedTiles,setMatchedTiles]=useState([]);
const[endOfTurn,setEndOfTurn]=useState(false);
const[score,setScore]=useState(0);
const[minutes,setMinutes]=使用状态(2);
常数[秒,设置秒]=使用状态(0);
常量[难度,设置难度]=使用状态(8);
const history=useHistory();
useffect(()=>{
getImages();
},[术语,难度];
useffect(()=>{
随机图像(图像);
},[图像];
useffect(()=>{
如果(分钟===0和秒===0){
finishGame();
}
},[秒,分];
const finishGame=()=>{
history.push(`/gamefinished`);
};
useffect(()=>{
如果(已启动){
让myInterval=setInterval(()=>{
如果(秒>0){
设置秒(秒-1);
}
如果(秒===0){
如果(分钟===0){
clearInterval(myInterval);
}否则{
设置分钟数(分钟-1);
设置秒(59);
}
}
}, 1000);
return()=>{
clearInterval(myInterval);
};
}
});
useffect(()=>{
if(matchedTiles.length>0&&matchedTiles.length===images.length/2){
警惕(“你赢了!”);
}
},[matchedTiles]);
const getImages=async()=>{
const response=wait unsplash.get(“/search/photos”{
参数:{query:searchImageTerm,每页:难度},
});
setImages(响应、数据、结果);
};
const generateTileId=()=>{
返回“tile_id_”+Math.random().toString().substr(2,8);
};
const randomiseImagesWithID=(图像)=>{
让duplicateImagesArray=[…图像,…图像];
var m=duplicateImagesArray.length,
T
我
while(m){
i=Math.floor(Math.random()*m--);
t=重复图像阵列[m];
DuplicateMageSarray[m]=DuplicateMageSarray[i];
重复图像array[i]=t;
}
设finalArray=[];
对于(让重复图像的图像为光线){
最后推({
…图像,
tileId:GenerateTimeId(),
});
}
setRandomisedImages([…最终结果]);
};
常量startRound=()=>{
setRoundStarted(true);
};
const onTileClick=(tileId,id)=>{
//瓷砖是否已配对&&瓷砖是否已选定&&回合是否结束?
如果(
!matchedTiles.包括(id)&&
tileId!==第一个选定文件&&
!endOfTurn
) {
//查找用于比较的第一个选定id的图像id
const firstSelctedTileId=randomisedImages.find(
(图像)=>image.tileId==firstSelectedFile
)?身份证;
//如果没有选定的磁贴,请设置第一个选定的磁贴
如果(!FirstSelectedFile){
SetFirstSelectedFile(tileId);
}否则{
//如果第二个磁贴与第一个磁贴匹配,则设置要包括的匹配磁贴
if(id==firstSelctedTileId){
setMatchedTiles([…matchedTiles,id]);
//加分得分
核心得分(得分+6分);
//重置选定的磁贴
SetFirstSelectedFile(空);
}否则{
//扣分
核心得分(得分-2分);
//设置并显示第二个平铺选项
SetSecondSelectedFile(tileId);
//设置回合结束,以便无法继续选择平铺
setEndOfTurn(真);
//几秒钟后重置所有值
设置超时(()=>{
SetFirstSelectedFile(空);
SetSecondSelectedFile(空);
setEndOfTurn(假);
}, 1500);
}
}
}
};
const onResetClick=()=>{
随机图像(图像);
SetFirstSelectedFile(空);
SetSecondSelectedFile(空);
setMatchedTiles([]);
设置核心(0);
setEndOfTurn(假);
};
返回(
);
}
导出默认应用程序;
const Container=styled.div`
宽度:100%;
高度:100vh;
显示:网格;
网格模板行:7rem;
`;
const Main=styled.div`
显示:网格;
网格模板列:自动;
`;
并举例说明我的代码在何处按预期工作:
import React from "react";
import { useHistory } from "react-router-dom";
import styled from "styled-components";
function LandingPage({ startRound }) {
const history = useHistory();
const startGame = () => {
history.push(`/gameboard`);
startRound();
};
const customiseGame = () => {
history.push("/customise");
};
return (
<Container>
<WelcomeText>
<p>Match the tiles by picking two at a time.</p>
<p>Gain points for a correct match but lose points if they dont.</p>
<p>Good Luck!</p>
</WelcomeText>
<ButtonContainer>
<GameButton onClick={() => startGame()}>Start</GameButton>
<GameButton onClick={() => customiseGame()}>Customise</GameButton>
</ButtonContainer>
</Container>
);
}
从“React”导入React;
从“react router dom”导入{useHistory};
从“样式化组件”导入样式化;
函数登录页({startRound}){
const history=useHistory();
常数startGame=(
npm uninstall react-router-dom && npm i react-router-dom
// First component
import { useHistory } from "react-router-dom";
const firstComponent = () => {
const history = useHistory();
return (
<SecondComponent history=history />
)
}
const SecondComponent = ({history}) => (
....
);
const history = useHistory();
const finishGame = () => {
const history = useHistory();
history.push(`/gamefinished`);
};