我试图在后端使用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
我知道我可能犯了一些入门错误,但是这个问题困扰了我一段时间。
答案 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。
以下是实现示例: State Management with Hooks
State Management with Hooks and Context
Redux可以用三个基本原理来描述:
单一事实来源:整个应用程序的状态存储在单个存储中的对象树中。
状态为只读:更改状态的唯一方法是发出一个动作,一个描述发生了什么的对象。
使用纯函数进行更改:要指定行为如何转换状态树,请编写纯reducer。
Redux documentation on the three core principles.
已经发布了许多其他用于状态管理的库。上面的选项可能是最常用的选项,但还有其他流行的选项,例如: