反应:使用App.js中的路由器在组件之间传递数据(父组件)

时间:2019-08-25 08:48:11

标签: javascript reactjs web react-router axios

我试图在后端使用Laravel框架时自学在前端使用React。我现在的目标是让用户通过表单注册(效果很好)。

在前端,有两个与此问题相关的组件,即父组件App.js,其中我的“ /”路由会自动加载,而所有其他路由都使用react路由器调用,如下所示:

`

<BrowserRouter>
        <div>
            {this.state.data_username}
        </div>
            <Header />

            <Footer />

            <Switch>
                <Route exact path='/' component={Intro} />
                <Route path='/register' component={Register} />
                <Route path='/login' component={Login}/>
                <Route path='/userpage' component={Userpage}/>
                <Route path='/science' component={Science}/>
                <Route path='/literature' component={Literature}/>

            </Switch>


        </BrowserRouter>

`

然后有一个子组件Register.js,我在其中进行axios帖子调用以注册用户。

目标:当用户注册后,我想将用户名(代码成功获得,因为我将其显示在控制台中)传递给父组件,然后传递给Header组件,因此我可以将其呈现屏幕。

我的理解是,我将从父组件到子组件进行回调,以某种方式将函数或对象传递给子组件,在子组件内分配所需的值,然后将其传递给Header。

我尝试过的是:

<Route path='/register'  render={props=>(<><Register    {...callbackFromParents}/></>)}

但是这没有用。 但是,我看到的大多数示例都没有使用react-router来处理路由。在这种情况下,我无法在Route代码中正确复制render方法。

这是我的代码:

import React, {Component} from 'react'
                    import ReactDOM from 'react-dom'
                    import {BrowserRouter, Route, Switch } from 'react-router-dom'
                    // import {Link} from 'react-router-dom'
                    import Header from './Header'
                    import Intro from './Intro'
                    import Register from './Register'
                    import Login from './Login'
                    import Userpage from './Userpage'
                    import Footer from './Footer'
                    import Science from './Science'
                    import Literature from './Literature'




                    class App extends Component {

                        constructor(props){
                            super(props);
                            this.state={
                                data_username:'Username'
                            }

                            this.username_Callback=this.username_Callback.bind(this)



                        }

                        username_Callback(usernamecallback){
                        this.setState({data_username:usernamecallback});

                    }



                        // username_attend(){
                        //     var username=data_username;
                        // }

                    // render={props=>(<><Register {...callbackFromParents}/></>)}



                        render(){
                            return(


                                <BrowserRouter>
                                <div>
                                    {this.state.data_username}
                                </div>
                                    <Header />

                                    <Footer />

                                    <Switch>
                                        <Route exact path='/' component={Intro} />
                                        <Route path='/register' component={Register} />
                                        <Route path='/login' component={Login}/>
                                        <Route path='/userpage' component={Userpage}/>
                                        <Route path='/science' component={Science}/>
                                        <Route path='/literature' component={Literature}/>

                                    </Switch>


                                </BrowserRouter>




                                )
                        }
                    }

                    ReactDOM.render(<App />, document.getElementById('app'))

和Register.js:

import React, {Component} from 'react'
    // import {Link} from 'react-router-dom'
    import axios from 'axios'


    class Register extends Component{
        constructor(props){
            super(props)
            this.state={
                name: '',
                email:'',
                password:'',
                errors:[]
            }

                this.handleFieldChange = this.handleFieldChange.bind(this)
            this.handleCreateNewUser = this.handleCreateNewUser.bind(this)
            this.hasErrorFor = this.hasErrorFor.bind(this)
            this.renderErrorFor = this.renderErrorFor.bind(this)


        }


    handleFieldChange(event) {
        this.setState({
          [event.target.name]: event.target.value
        })
    }

    handleCreateNewUser(event) {
            event.preventDefault()

            const { history } = this.props

            const user = {
              name: this.state.name,
              email: this.state.email,
              password: this.state.password

            }

            axios.post('/api/register', user)
              .then(response => {
                console.log('Success',response.data.flag)
                console.log('Success',response.data.username)
                this.props.callbackFromParent(response.data.username)
                // redirect to the homepage
                history.push('/')
              })
              .catch(error => {
                this.setState({
                  errors: error.response.data.errors
                })
              })
          }




    hasErrorFor(field) {
            return !!this.state.errors[field]
          }

    renderErrorFor(field) {
        if (this.hasErrorFor(field)) {
          return (
            <span className='invalid-feedback'>
              <strong>{this.state.errors[field][0]}</strong>
            </span>
          )
        }
    }



    render(){

        return (

    <div className='container py-4'>
          <div className='row justify-content-center'>
            <div className='col-md-6'>
              <div className='card'>
                <div className='card-header'>Create new account</div>
                <div className='card-body'>

                  <form onSubmit={this.handleCreateNewUser} >

                    <div className='form-group'>
                      <label htmlFor='name'>User Name</label>
                      <input
                        id='name'
                        className={`form-control ${this.hasErrorFor('name') ? 'is-invalid' : ''}`}
                        name='name'
                        value={this.state.name}
                        onChange={this.handleFieldChange}
                      />
                    </div>

                    <div className='form-group'>
                      <label htmlFor='description'>Email</label>
                      <input
                        id='email'
                        className={`form-control ${this.hasErrorFor('email') ? 'is-invalid' : ''}`} 
                        name='email'
                        value={this.state.email}
                        onChange={this.handleFieldChange}
                      />
                    </div>

                    <div className='form-group'>
                      <label htmlFor='description'>Password</label>
                      <input
                        id='password'
                        className={`form-control ${this.hasErrorFor('password') ? 'is-invalid' : ''}`}
                        name='password'
                        value={this.state.password}
                        onChange={this.handleFieldChange}
                      />
                    </div>

                    <button type='submit' className='btn btn-primary'>Register</button>
                  </form>
                </div>
              </div>
            </div>
          </div>
        </div>  

        )
      }
    }
    export default Register

我知道我可能犯了一些入门错误,但是这个问题困扰了我一段时间。

2 个答案:

答案 0 :(得分:1)

您处于正确的轨道。为了通过路由传递功能,您应该执行以下操作:

<Route path='/register'  render={props=><Register {...props} 
                          callbackFromParents= {this.username_Callback}}/>

,然后在axios响应的 Register.js 中:

//Note the plural and not plural in your code
this.props.callbackFromParents(response.data.username)

答案 1 :(得分:1)

对于您而言,在全球范围内存储此类数据可能会有益,而不是手动传递。这可能是您做出反应的下一步。

当心,React为开发人员提供了极大的自由,您可能会偶然发现很多解决问题的选项。这就是为什么我首先列出了两种内置方法,并添加了其他库以供以后检出的原因。他们增加了一些复杂性,并且拥有自己的学习曲线。

即使您不使用我提供的解决方案,也可以将其用作概述和未来方向。

为什么要关心应用程序中的数据存储?

想象一下,您不仅需要传递名称,还需要在多个组件中传递名称。或者您也需要其他组件中的该行为。您是否总是想像这样手动实现它?如果这些信息分散在整个应用程序中,那么某人(对代码而言是新的还是对您而言,是新手)如何很好地了解发生了什么。还有,如果您决定将部分数据保存在浏览器缓存中呢?

有哪些选项?

反应上下文

  

上下文旨在共享可以被视为“全局”的数据   反应组件树,例如当前经过身份验证的用户,   主题或首选语言。

React documentation on Context

React Context是React的一部分,可能是探索数据存储的最简单/最快的方法。即使您决定使用其他解决方案,也请查看上下文并检查其工作方式。无论如何,这是React的重要组成部分。

反应钩

  

使用Hooks,您可以从组件中提取状态逻辑,以便它可以   进行独立测试并重复使用。挂钩允许您重用有状态   逻辑而无需更改组件层次结构。这很容易   在许多组件之间或与社区共享Hook。

React documentation on Hooks

以下是实现示例: State Management with Hooks

State Management with Hooks and Context

Redux库

  

Redux可以用三个基本原理来描述:

     

单一事实来源:整个应用程序的状态存储在单个存储中的对象树中。

     

状态为只读:更改状态的唯一方法是发出一个动作,一个描述发生了什么的对象。

     

使用纯函数进行更改:要指定行为如何转换状态树,请编写纯reducer。

Redux documentation on the three core principles.

其他状态库

已经发布了许多其他用于状态管理的库。上面的选项可能是最常用的选项,但还有其他流行的选项,例如:

相关问题