React Router Params

问题描述 投票:1回答:1

晚上好,所以我试图使用react router参数加载我的编辑页面,但出现此错误-无法读取未定义的属性'params'。

在我的编辑页面中,props.match.params._id位于一个单独的Submit组件(在页面顶部)中,而不是导出的组件,然后在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;
javascript reactjs express react-router react-router-dom
1个回答
0
投票

假设“编辑”组件的道具中获得正确的值,您可以在“编辑”中移动“提交”以共享相同的道具。像这样:


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>
  );
};

© www.soinside.com 2019 - 2024. All rights reserved.