简体   繁体   English

来自两个不同组件的React中的传递状态

[英]Passing state in React from two different components

I have a TopNab bar (component), which contains a SearchBar component. 我有一个TopNab栏(组件),其中包含SearchBar组件。 My Main component is rendering out TopNav, the main container component (Profile), and the Footer component. 我的主要组件是渲染TopNav,主要容器组件(配置文件)和页脚组件。 I want my SearchBar component to pass its state to the main container component so that the Profile component can use it. 我希望我的SearchBar组件将其状态传递给主容器组件,以便Profile组件可以使用它。

What I am trying to build: A user types a name into search bar and submits. 我要构建的内容:用户在搜索栏中输入名称并提交。 The profile matching the user name is displayed in the main container component. 与用户名匹配的配置文件显示在主容器组件中。

Right now I have a component that can render out user profiles. 现在,我有一个可以呈现用户个人资料的组件。 I also have a component thats state updates to the user submitted value. 我也有一个组件,可以将状态更新为用户提交的值。 What I need to do is pass this user submitted value to my profile component in order to render out the correct profile. 我需要做的是将此用户提交的值传递给我的个人资料组件,以呈现正确的个人资料。

Is this possible or do I need to rebuild my components so the search is included in the Profile component? 这是否可能,或者我是否需要重建组件,以便搜索包含在Profile组件中?

SearchBar 搜索栏

import React, { Component, PropTypes } from 'react';
import Profile from './Profile';


class SearchBar extends Component {
    constructor(props){
        super(props)
            this.state = {
                name: ''
            }
    }

    handleChange(e) {
        this.setState({
            name: e.target.value
        });
    }

    handleSubmit(e) {
            e.preventDefault();
            console.log("searching for NAME " + this.state.name);
            let profileName = this.state.name;
            //PASS STATE TO PROFILE COMPONENT
        }

    render() {
        return (
            <div>
                <form onSubmit={this.handleSubmit.bind(this)}>
                    ARMORY BETA
                    <input type="text" placeholder="Enter Name" 
                    name="name" 
                    value={this.state.name} 
                    onChange={this.handleChange.bind(this)} />
                    <button className="btn btn-success" type="submit">Search</button>
                </form>
            </div>
        )
    }
}

export default SearchBar;

Profile 轮廓

import React, { Component, PropTypes } from 'react';
import SearchBar from './SearchBar';
import ProfileContainer from '../containers/ProfileContainer';

class Profile extends Component {

    render() {
        return (
            <div className="cols2">
                <div>[IMG]</div>
                <div>
                    <ProfileContainer name={this.props.name}/>
                </div>
            </div>
        )
    }
}

Profile.PropTypes = {
    name: PropTypes.string
}

Profile.defaultProps = {
    name: ''
}

export default Profile;

Main 主要

import React, { Component } from 'react';
import TopNav from './TopNav';
import Footer from './Footer';
import Profile from './Profile';

class Main extends Component {
    render() {
        return (
            <div className="container-fluid">
                <div className="row">
                    //TopNav calls SearchBar
                    <TopNav />
                </div>
                <div className="row">
                    <Profile />
                </div>
                <div className="row">
                    <Footer />
                </div>
            </div>
        )
    }
}


export default Main;

You'll need to expose a property on SearchBar that accepts a callback that will be called to indicate to its parent that the form was submitted (eg onSubmit)... 您需要在SearchBar上公开一个属性,该属性接受一个回调,该回调将被调用以指示其父项表单已提交(例如onSubmit)...

handleSubmit(e) {
        e.preventDefault();
        console.log("searching for NAME " + this.state.name);
        let profileName = this.state.name;
        //PASS STATE TO PROFILE COMPONENT
        this.props.onSubmit(yourFormData);
    }

...TopNav won't handle onSubmit itself, but just pass it on up to its own parent (perhaps renaming to "onSearchBarSubmit" along the way to make the name clearer from the perspective of TopNav's parent): ... TopNav不会自行处理onSubmit,而只会将其传递给它自己的父级(也许会从TopNav父级的角度更名为“ onSearchBarSubmit”,以使名称更清晰):

class TopNav extends Component {
    render() {
        return (
            <div className="container-fluid">
              <SearchBar onSubmit={this.props.onSearchBarSubmit}
            </div>
        );
    }
}

class Main extends Component {
    render() {
        return (
            <div className="container-fluid">
                <div className="row">
                    <TopNav onSearchBarSubmit={ (criteria) => this.searchForStuff(criteria) } />
                </div>
                <div className="row">
                    <Profile data={this.state.stuffYouGotBackFromSearch} />
                </div>
                <div className="row">
                    <Footer />
                </div>
            </div>
        )
    }
}

...OR, in some cases, it can be desirable to un-nest the components, allowing SearchBar as one of TopNav 's props.children . ...或者,在某些情况下,可能希望取消嵌套组件,使SearchBar成为TopNavprops.children This allows you to handle onSubmit directly within Main, and pass anything it receives onto Profile: 这使您可以直接在Main内部处理onSubmit,并将接收到的任何内容传递到Profile:

class Main extends Component {
    render() {
        return (
            <div className="container-fluid">
                <div className="row">
                    //TopNav calls SearchBar
                    <TopNav>
                      <SearchBar onSubmit={ (criteria) => this.searchForStuff(criteria) } />
                    </TopNav>
                </div>
                <div className="row">
                    <Profile data={this.state.stuffYouGotBackFromSearch} />
                </div>
                <div className="row">
                    <Footer />
                </div>
            </div>
        )
    }
}

...a side-benefit of un-nesting is that it would allow you to use TopNav and Searchbar independently. ...取消嵌套的好处是,您可以单独使用TopNav和Searchbar。

In Main , you should add a prop to <TopNav /> that points to a handler method that will propagate the profileName state change back to Main . Main ,应该在<TopNav />中添加一个道具,该道具指向一个处理程序方法,该方法将profileName状态更改传播回Main This, in turn, will cause Profile to be re-rendered. 反过来,这将导致重新渲染Profile The handler method takes one argument profileName and is called from the handleSubmit method in TopNav . 该处理程序方法采用一个参数profileName并从handleSubmit方法中TopNav Here's the code: 这是代码:

SearchBar 搜索栏

class SearchBar extends Component {
    . . .
    handleSubmit(e) {
        e.preventDefault();
        console.log("searching for NAME " + this.state.name);
        let profileName = this.state.name;
        this.props.handleProfileChange(profileName);
    }
    . . .
}
SearchBar.propTypes = {
  handleProfileChange: React.PropTypes.func.isRequired,
}

Main 主要

class Main extends Component {
   constructor(props) {
     super(props);
     this.state = { profileName: '' }
     handleProfileChange = this.handleProfileChange.bind(this);
   }

   handleProfileChange(profileName) {
     // This state change will force Profile component to be re-rendered
     this.setState( { profileName });
   }

   render() {
     return (
        <div className="container-fluid">
            <div className="row">
                //TopNav calls SearchBar
                <TopNav handleProfileChange={this.handleProfileChange} />
            </div>
            <div className="row">
                <Profile profileName={this.state.profileName} />
            </div>
            <div className="row">
                <Footer />
            </div>
        </div>
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM