反应路由器参数
Posted
技术标签:
【中文标题】反应路由器参数【英文标题】:React Router Params 【发布时间】:2020-10-02 20:02:21 【问题描述】:晚上好,所以我正在尝试使用加载我的编辑页面,但我收到此错误 - 无法读取未定义的属性“参数”。
在我的编辑页面中,props.match.params._id 位于一个单独的提交组件中(在页面顶部),而不是导出的那个,然后在 App.js 上为路由导入。
正因为如此,我相信它导致了我的问题,但经过一些澄清后我不确定。
我确实将 props 传递给两个组件,我是否需要在 Edit 组件中的某个地方包含 props.match.params._id。
我担心 Edit 组件有点混乱,能否将组件从外部拆分出来,会有帮助吗?
编辑组件
import MyTestStore from "./App";
import AppContext from './context';
import "react-dropzone-uploader/dist/styles.css";
import Dropzone from "react-dropzone-uploader";
import styled from "styled-components";
import axios from "axios";
import withRouter from 'react-router-dom';
// import "./xApp.css";
import Clear from "@material-ui/icons";
// import withRouter from 'react-router-dom';
// import './style.css';
const MainContainer = styled.main`
grid-area: main;
display: grid;
grid-template-columns: 1fr;
margin: 0;
`;
const MovieForm = styled.form`
display: grid;
grid-template-columns: 1fr 25%;
height: 100vh;
width: 100%;
margin: 0;
`;
const MovieInfo = styled.div`
padding: 80px;
`;
const MoviePosters = styled.div`
background: lightgrey;
padding: 80px 40px;
`;
const HideMe = styled.div`
height: 470px;
overflow-y: auto;
overflow-x: hidden;
background: gainsboro;
border: 1px solid lavender;
`;
const Submit = props =>
const files, onSubmit = props;
const movie, setShowLoading, setMovie = useContext(AppContext);
const apiUrl = "http://localhost:5000/api/movies/" + props.match.params._id;
useEffect(() =>
setShowLoading(false);
const fetchData = async () =>
const result = await axios(apiUrl);
setMovie(result.data);
console.log(result.data);
setShowLoading(false);
;
fetchData();
, [apiUrl]);
const handleSubmit = () =>
console.log( movie );
console.log(files.map(f => f.meta));
const headers = "multipart/form-data";
const formData = new FormData();
formData.set("title", movie.title);
formData.set("date", movie.date);
formData.set("synopsis", movie.synopsis);
formData.set("vID", movie.vID);
formData.set("trailer", movie.trailer);
files.map(fileItem => formData.append("poster", fileItem.file));
console.log(Array.from(formData));
axios
.post(apiUrl, formData, headers)
.then(result =>
setShowLoading(false);
console.log(result);
props.history.push("/show/" + result.data.movie._id);
)
.catch(error => setShowLoading(false));
onSubmit();
;
return (
<div className="dzu-submitButtonContainer">
<button onClick=handleSubmit className="dzu-submitButton">
Submit
</button>
</div>
);
;
const Preview = ( meta, fileWithMeta ) =>
const previewUrl, name, status, percent = meta;
// const uploadPercentage, setUploadPercentage = useContext(AppContext);
// const timeout = useRef();
// console.log( status );
// useEffect(() =>
// const time = 10000;
// if (uploadPercentage < 100)
// timeout.current = setTimeout(() =>
// setUploadPercentage(uploadPercentage => uploadPercentage + 1);
// , time / 1000);
//
// return () => clearTimeout(timeout.current);
// , []);
// console.log(uploadPercentage);
return (
<div className="dzu-previewContainer">
<img class="dzu-previewImage" src=previewUrl alt=name title=name />
status === 'done' ? <Clear onClick=fileWithMeta.remove /> : ""
</div>
);
;
const Layout = (
input,
previews,
submitButton,
dropzoneProps,
files,
extra: maxFiles
) =>
return (
<div>
<div>
submitButton
<HideMe>
<div ...dropzoneProps>
previews
files.length < maxFiles && input
</div>
</HideMe>
</div>
</div>
);
;
const MyUploader = () =>
return (
<Dropzone
autoUpload=false
SubmitButtonComponent=Submit
PreviewComponent=Preview
LayoutComponent=Layout
onSubmit=() =>
console.log("After submit?");
inputContent="Drop Files (Custom Layout)"
/>
);
;
const Edit = (props) =>
const user, verified, setState = useContext(MyTestStore);
const movie, setMovie, showLoading = useContext(AppContext);
return (
// <AppContext.Provider value=values>
<MainContainer>
<MovieForm>
<MovieInfo>
showLoading && <span className="sr-only">Loading...</span>
<h2 className="title">Add Movie</h2>
<div className="wrapper">
<span>Title</span>
<input
className="no-outline"
type="text"
name="title"
defaultValue=movie.title
onChange=e => setMovie( ...movie, title: e.target.value )
placeholder="Film Title"
/>
</div>
<div className="wrapper">
<span>Date</span>
<input
className="no-outline"
type="date"
name="date"
defaultValue=movie.date
onChange=e => setMovie( ...movie, date: e.target.value )
/>
</div>
<div className="wrapper">
<span>Synopsis</span>
<textarea
className="no-outline"
type="text"
name="synopsis"
defaultValue=movie.synopsis
onChange=e => setMovie( ...movie, synopsis: e.target.value )
placeholder="Synopsis"
/>
</div>
<div className="wrapper">
<span>Movie ID</span>
<input
className="no-outline"
type="text"
name="vID"
defaultValue=movie.id
onChange=e => setMovie( ...movie, vID: e.target.value )
placeholder="Veezi Film ID"
/>
</div>
<div className="wrapper">
<span>Trailer</span>
<input
className="no-outline"
type="text"
name="trailer"
defaultValue=movie.trailer
onChange=e => setMovie( ...movie, trailer: e.target.value )
placeholder="Trailer URL"
/>
</div>
</MovieInfo>
<MoviePosters>
<MyUploader />
</MoviePosters>
</MovieForm>
</MainContainer>
// </AppContext.Provider>
);
;
export default withRouter(Edit);
应用程序路由
import Route, Switch, Router from "react-router-dom";
import createBrowserHistory from "history";
import checkLoggedIn from "../util/session";
import "./xApp.css";
// import "../script";
import AuthRoute, ProtectedRoute from "./Login";
import AddFilm from "./AddFilm";
import Movies from "./xMovies";
import Welcome from "./Welcome";
import Login from "./Login";
import Signup from "./Signup";
import Admin from "./xAdmin";
import Dashboard from "./xDashboard";
import AdminPage from "./xPage";
import EditPage from "./EditPage";
import Create from "./Create";
// import CreateForm from "./CreateForm";
import Edit from "./EditForm";
import Show from "./Show";
import List from "./List";
import Reviews from "./Reviews";
import BoxOffice from "./BoxOffice";
import Trash from "./Trash";
const history = createBrowserHistory();
export const MyTestStore = React.createContext()
export default ((props) =>
const [state, setState] = useState()
useEffect(() =>
async function appCheckLoggedIn()
const result = await checkLoggedIn();
if (result)
console.log(user, verified: true)
console.log(result.session);
const user = result.session
setState(user, verified: true)
else
console.log(verified: true)
setState(verified: true)
// Execute the created function directly
appCheckLoggedIn();
, [])
const loggedIn = !!state.user
return (
<>
<MyTestStore.Provider value=...state, setState>
<Router history=history>
<Switch>
<Route exact path="/" component=Welcome />
<Route path="/list" component=List />
<AuthRoute path="/login" component=Login />
<AuthRoute path="/signup" component=Signup />
<ProtectedRoute exact path="/admin" component=Dashboard layout=AdminPage />
<ProtectedRoute exact path="/admin/movies" component=Movies layout=AdminPage />
<ProtectedRoute exact path="/admin/movies/new" component=Create layout=EditPage />
<ProtectedRoute path="/admin/movies/edit/:_id" component=Edit layout=EditPage />
<ProtectedRoute exact path='/admin/movies/show/:_id' component=Show layout=AdminPage />
<ProtectedRoute exact path="/admin/reviews" component=Reviews layout=AdminPage />
<ProtectedRoute exact path="/admin/box-office" component=BoxOffice layout=AdminPage />
<ProtectedRoute exact path="/admin/trash" component=Trash layout=AdminPage />
loggedIn && <Admin /> || null
</Switch>
</Router>
</MyTestStore.Provider>
</>
))
快速路线
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser')
const upload = require('../config/multer.config.js');
const app = express();
fs = require('fs-extra')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(extended: true))
// Load Movie model
const Movie = require('../models/movie');
// @route GET api/movies/test
// @trailer tests movies route
// @access Public
router.get('/test', (req, res) => res.send('movie route testing!'));
// @route GET api/movies
// @trailer Get all movies
// @access Public
router.get('/', (req, res) =>
Movie.find()
.then(movies => res.json(movies))
.catch(err => res.status(404).json( nomoviesfound: 'No Movies found' ));
);
// @route GET api/movies/:id
// @trailer Get single movie by id
// @access Public
router.get('/:id', (req, res) =>
Movie.findById(req.params.id)
.then(movie => res.json(movie))
.catch(err => res.status(404).json( nomoviefound: 'No Movie found' ));
);
// @route GET api/movies
// @trailer add/save movie
// @access Public
router.post('/', upload.array('poster'), (req, res) =>
var filenames = req.files.map(function(file)
return file.path; // or file.originalname
);
var a = (filenames.findIndex(function(item)
return item.indexOf("poster")!==-1;
));
var b = (filenames.findIndex(function(item)
return item.indexOf("slide")!==-1;
));
console.log(filenames);
// console.log(movieData);
// console.log(req.body);
// console.log(req.files);
var date = new Date(req.body.date);
// var isoString = date.toISOString();
var movieData =
id: req.body.id,
title: req.body.title,
synopsis: req.body.synopsis,
trailer: req.body.trailer,
OpeningDate: date,
poster: filenames[a],
slide: filenames[b]
;
let movie = new Movie(movieData);
movie.save()
.then(() => res.json( movie, msg: 'New movie added successfully' ))
.catch(err => res.status(400).json('Unable to add this movie'))
);
// @route GET api/movies/:id
// @trailer Update movie
// @access Public
router.post('/:id', upload.array('posters'), (req, res) =>
Movie.findByIdAndUpdate(req.params.id)
.then(movie =>
movie.id = req.body.id,
movie.title = req.body.title,
movie.synopsis = req.body.synopsis,
movie.trailer = req.body.trailer
console.log(req.files);
console.log(req.files.length);
if (req.files.length > 0)
console.log('hi');
var filenames = req.files.map(function(file)
return file.path; // or file.originalname
);
var a = (filenames.findIndex(function(item)
return item.indexOf("poster")!==-1;
));
var b = (filenames.findIndex(function(item)
return item.indexOf("slide")!==-1;
));
console.log(a);
if (a >= 0)
movie.poster = filenames[a]
if (b >= 0)
movie.slide = filenames[b]
console.log(movie);
movie.save()
.then(() => res.json( movie, msg: 'Updated successfully' ))
.catch(err =>
res.status(400).json('Unable to update the Database'))
)
.catch(err =>
res.status(400).json('Unable to update the Database'));
);
// @route GET api/movies/:id
// @trailer Delete movie by id
// @access Public
router.delete('/:id', (req, res) =>
Movie.findByIdAndRemove(req.params.id)
.then(() => res.json('Movie entry deleted successfully'))
.catch(err => res.status(404).json( error: 'No such a movie' ));
);
module.exports = router;
【问题讨论】:
【参考方案1】:假设 Edit 组件在其 props 中获取正确的值,您可以在 Edit 中移动 Submit 以共享相同的 props。所以像:
const Edit = (props) =>
...
const Submit = () =>
// here you'll have access to the props passed into Edit
...
;
const Preview = (...) =>
...
;
const Layout = (...) =>
...
;
const MyUploader = () =>
...
;
return (
<MainContainer>
...
</MainContainer>
);
;
【讨论】:
以上是关于反应路由器参数的主要内容,如果未能解决你的问题,请参考以下文章