【问题标题】:Passing state in React from two different components从两个不同的组件传递 React 中的状态
【发布时间】:2017-05-19 10:22:46
【问题描述】:

我有一个 TopNab 栏(组件),其中包含一个 SearchBar 组件。我的主要组件正在渲染 TopNav、主要容器组件(配置文件)和页脚组件。我希望我的 SearchBar 组件将其状态传递给主容器组件,以便 Profile 组件可以使用它。

我正在尝试构建的内容: 用户在搜索栏中输入名称并提交。 与用户名匹配的配置文件显示在主容器组件中。

现在我有一个可以呈现用户配置文件的组件。我还有一个组件,它可以对用户提交的值进行状态更新。我需要做的是将此用户提交的值传递给我的配置文件组件,以便呈现正确的配置文件。

这是可能的还是我需要重新构建我的组件以便将搜索包含在 Profile 组件中?

搜索栏

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;

简介

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;

主要

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;

【问题讨论】:

    标签: reactjs search components state


    【解决方案1】:

    Main 中,您应该向&lt;TopNav /&gt; 添加一个指向处理程序方法的属性,该方法将profileName 状态更改传播回Main。这反过来又会导致Profile 被重新渲染。处理程序方法接受一个参数profileName,并从TopNav 中的handleSubmit 方法调用。代码如下:

    搜索栏

    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,
    }
    

    主要

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

    【讨论】:

    • 今天会试试这个 - 并报告 - ty
    【解决方案2】:

    您需要在 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 不会自己处理 onSubmit,而只是将它传递给它自己的父级(可能在此过程中重命名为“onSearchBarSubmit”,以使名称从 TopNav 的父级的角度来看更清晰):

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

    ...或者,在某些情况下,可能需要取消嵌套组件,允许SearchBar 作为TopNavprops.children 之一。这允许您直接在 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>
            )
        }
    }
    

    ...取消嵌套的一个附带好处是它允许您独立使用 TopNav 和 Searchbar。

    【讨论】:

    • 今天也试试这个方法,反馈一下-ty
    • TopNav 取消嵌套方法导致涉及 和下面的
      的关闭 JSX 标记错误
  • 好的,我关闭了代码sn-p中的标签。这并不是真正的文字代码,它只是在 SO 编辑器中完成的代码的复制/粘贴/编辑。我希望你仍然能够推导出我描述的概念。祝你好运!
  • 猜你喜欢
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-15
    • 2021-01-11
    • 2021-11-06
    • 2019-09-29
    • 1970-01-01
    相关资源
    最近更新 更多