Reactjs 将状态传递给React中的多个子组件

Reactjs 将状态传递给React中的多个子组件,reactjs,react-router,Reactjs,React Router,我很难理解如何将状态作为道具传递给React中的其他子组件。在我的代码中,您可以看到我有一个组件,该组件接收输入并将其映射到我的状态数组,在另一个组件中显示部分数据,工作正常 但总体目标是,当用户单击他们添加到列表中的项目时,React Router将启动并将视图更改为MovieDetails组件,该组件将包含他们输入的额外信息,如标题、日期和描述 我甚至还没有设置react路由器,因为我似乎无法正确访问MovieDetails组件中的状态。然后我不太确定如何用路由器显示正确的MovieDeta

我很难理解如何将状态作为道具传递给React中的其他子组件。在我的代码中,您可以看到我有一个组件,该组件接收输入并将其映射到我的状态数组,在另一个组件中显示部分数据,工作正常

但总体目标是,当用户单击他们添加到列表中的项目时,React Router将启动并将视图更改为MovieDetails组件,该组件将包含他们输入的额外信息,如标题、日期和描述

我甚至还没有设置react路由器,因为我似乎无法正确访问MovieDetails组件中的状态。然后我不太确定如何用路由器显示正确的MovieDetails组件

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import './App.css';

class App extends Component {
  constructor() {
    super();
    this.addMovie = this.addMovie.bind(this);
    this.state = {
      movies : []
    };
  }

  addMovie(movie) {
    let movies = this.state.movies;
    movies.push(movie);
    this.setState({ movies });
  }

  render() {
    return (
      <div className="wrapper">
        <div className="container">
          <div>
            <h3 className="heading">Favorite Movies</h3>
          </div>
        </div>
        <div>
          <AddMovie addMovie={ this.addMovie }/>
          <MovieList movies={ this.state.movies }/>
        </div>
      </div>
    )
  }
}

class AddMovie extends Component {
  addMovie(event) {
    event.preventDefault();
    const movie = {
      title : this.title.value,
      year  : this.year.value,
      image : this.image.value,
      desc  : this.desc.value
    }
    this.props.addMovie(movie);
    this.movieForm.reset();
  }
  render() {
    return (
      <div className="container">
        <form ref={(input) => this.movieForm = input} onSubmit={(e) => this.addMovie(e)}>
          <input ref={(input) => this.title = input} className="Input" type="text" placeholder="Title"/>
          <input ref={(input) => this.year = input} className="Input" type="text" placeholder="Year"/>
          <textarea ref={(input) => this.desc = input} className="Input" type="text" placeholder="Description"></textarea>
          <input ref={(input) => this.image = input} className="Input" type="text" placeholder="Poster URL"/>
          <button type="submit">Add</button>
        </form>
      </div>
    )
  }
}

class MovieList extends Component {
  render() {
    return (
      <div>
        { this.props.movies.map( (movie, i) => <MovieListItem key={i} details={ movie }/> )}
      </div>
    );
  }
}

class MovieListItem extends Component {
  constructor(props) {
    super(props);
    this.toggleClass = this.toggleClass.bind(this);
    this.state = {
      active: false
    };
  }
  toggleClass() {
    const currentState = this.state.active;
    this.setState({ active: !currentState });
  }
  render() {
    const { details } = this.props;
    return (
      <div
        className={this.state.active ? "red": null}
        onClick={this.toggleClass}
      >
        <img src={details.image} alt=""/>
        <hr/>
      </div>
    )
  }
}

class MovieDetails extends Component {
  render() {
    return (
      <div>
        <p>title here</p>
        <p>year here</p>
        <p>description here</p>
        <img src="image" alt=""/>
      </div>
    )
  }
}

export default App;
import React,{Component}来自'React';
从“react Router dom”导入{BrowserRouter as Router,Route,Link};
导入“/App.css”;
类应用程序扩展组件{
构造函数(){
超级();
this.addMovie=this.addMovie.bind(this);
此.state={
电影:[]
};
}
addMovie(电影){
让电影=this.state.movies;
电影。推送(电影);
this.setState({movies});
}
render(){
返回(
最喜欢的电影
)
}
}
类AddMovie扩展组件{
addMovie(事件){
event.preventDefault();
康斯特电影={
标题:this.title.value,
年份:this.year.value,
image:this.image.value,
desc:this.desc.value
}
this.props.addMovie(电影);
这个.movieForm.reset();
}
render(){
返回(
this.movieForm=input}onSubmit={(e)=>this.addMovie(e)}>
this.title=input}className=“input”type=“text”placeholder=“title”/
this.year=input}className=“input”type=“text”placeholder=“year”/
this.desc=input}className=“input”type=“text”placeholder=“Description”>
this.image=input}className=“input”type=“text”placeholder=“Poster URL”/>
添加
)
}
}
类MovieList扩展组件{
render(){
返回(
{this.props.movies.map((movie,i)=>)}
);
}
}
类MovieListItem扩展了组件{
建造师(道具){
超级(道具);
this.toggleClass=this.toggleClass.bind(this);
此.state={
活动:错误
};
}
toggleClass(){
const currentState=this.state.active;
this.setState({active:!currentState});
}
render(){
const{details}=this.props;
返回(

) } } 类MovieDetails扩展组件{ render(){ 返回( 标题在这里

今年

描述在这里

) } } 导出默认应用程序;
如果我答对了,当您单击从MovieList创建的项目时,是否要推送到一个新组件(在该组件中,
详细信息应该可以访问)?如果是这样,以下是您必须执行的步骤:

  • 如果你想推送一个新视图,你必须使用类似“react router”的
    browserHistory
    hashHistory
    。在本例中,我将使用
    browserHistory
  • 要访问
    MovieDetails
    组件中的状态,只需将其通过
    browserHistory
    即可
  • 以下是当单击MovieList组件中的项目时,我使用您的代码推送到新视图的方式:

    import {Router, Route, browserHistory} from "react-router";
    
    class Routes extends Component {
      render() {
        let props = this.props;
    
        return (
          <Router history={browserHistory}>
            <Route path="/" component={App}/>
            <Route path="/movie-details" component={MovieDetails}/>
          </Router>
        )
      }
    }
    
    // Here is your App component
    class App extends Component {
      // ... your code
    }
    
    // ... your other classes
    
    
    class MovieListItem extends Component {
      // ... Constructor 
      // Here I'm pushing the new route for MovieDetails view
      toggleClass(details) {
        browserHistory.push({
          pathname: '/movie-details',
          state: details // pass the state to MovieDetails
        });
        // ... your code
      }
    
      render() {
        const {details} = this.props;
    
        return (
          <div
           // ... your code
           onClick={this.toggleClass.bind(this, details)} // pass details to toggleClass() 
          >
          // ... your code
          </div>
        )
      }
    }    
    
    // Here is your Movie Details component
    class MovieDetails extends Component { 
      console.log('This props: ', this.props.location.state); // The details object should be logged here
      // ... your code
    }
    
    // Export Routes instead of App
    export default Routes;
    
    从“react Router”导入{Router,Route,browserHistory};
    类路由扩展组件{
    render(){
    让props=this.props;
    返回(
    )
    }
    }
    //这是你的应用程序组件
    类应用程序扩展组件{
    //…您的代码
    }
    // ... 你的其他课程
    类MovieListItem扩展了组件{
    //…构造器
    //在这里,我正在推动电影细节视图的新路线
    toggleClass(详细信息){
    浏览历史({
    路径名:'/movie details',
    state:details//将状态传递给MovieDetails
    });
    //…您的代码
    }
    render(){
    const{details}=this.props;
    返回(
    //…您的代码
    )
    }
    }    
    //这是您的电影详细信息组件
    类MovieDetails扩展组件{
    console.log('This props:',This.props.location.state);//应该在这里记录详细信息对象
    //…您的代码
    }
    //导出路由而不是应用程序
    导出默认路径;
    

    希望有帮助

    问题来自您尝试访问输入值的方式。使用
    ref
    时,会得到一个React包装器,而不是真正的DOM元素,因此无法直接访问
    .value
    .reset()
    。您必须使用
    getDOMNode()
    方法来获取DOM元素。这对我很有用:

    const movie = {
      title : this.title.getDOMNode().value,
      year  : this.year.getDOMNode().value,
      image : this.image.getDOMNode().value,
      desc  : this.desc.getDOMNode().value
    };
    
    ...
    
    this.movieForm.getDOMNode().reset();
    
    另一件事,当您
    setState
    使用当前状态的内容时,您应该使用回调:

    addMovie(newMovie) {
      this.setState(({movies: prevMovies})=> ({
        movies: [...prevMovies, newMovie]
      }));
    }
    

    请参阅

    中的完整
    setState
    API,我不太明白您的问题出在哪里。你能试着做一个狙击手,或者一个密码笔吗?花了我一分钟,它不太正常,但它在密码笔上:对不起!隐马尔可夫模型。。。我知道你要去哪里,但我试过了,现在它只加载MovieDetails组件,我的测试内容显示在页面上。我不能强迫它进入主页——它一直在加载电影细节的路径。我在尝试访问MovieDetails中的MovieListItem数据时仍然出错。再说一次,您确定我的流正确吗?在这里,您可以看到
    MovieDetails
    组件中接收到的流程和道具。我编辑了我的代码,因此
    toggleClass
    从单击事件绑定。此外,我还记录了应该被接收到
    MovieDetails
    组件中的状态的孔路径。哦!哇!它起作用了。好的,我使用
    match.params
    和gra使它工作