我正在构建一个基本的表单设置,但是需要获取更改之前用户的数据,以便他们可以从该数据进行编辑。首次加载页面时,一切正常,但是刷新页面(F5)后,我得到了错误:Unhandled Rejection (TypeError): Cannot read property 'userFirstName' of null
。我第二次刷新页面时没有抓住userId。如果我离开该页面并转到另一个页面并返回,它将重新加载。如何使页面始终在刷新页面时重新获取数据?
我正在使用React.js,Firebase和React-router
Settings.js:
import React, { Component } from 'react';
import fire from '../../config/Fire.js';
export default class Settings extends Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.update = this.update.bind(this);
this.userDatabase = fire.database().ref().child('users');
this.state = {
userId: this.props.user.uid,
userFirstName: '',
};
}
componentWillMount(){
fire.database().ref('/users/' + this.state.userId).once('value').then(function(snapshot) {
var first_name = (snapshot.val().userFirstName);
this.setState({
userFirstName: first_name,
})
}.bind(this));
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
}
update(e){
e.preventDefault();
//update here
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{ this.props.history.push('/about') }).catch((error) => {
alert(error);
});
}
render() {
return (
<div className="m-container">
<h1>Hello, {this.state.userFirstName}</h1>
<hr/>
<p>Here are your settings details:</p>
<label for="first-name">First Name: </label>
<br/>
<input
value={this.state.userFirstName}
onChange={this.handleChange}
type="text"
name="first-name"
id="first-name"
placeholder={this.state.userFirstName}
/>
<br/>
<br/>
<button
type="submit"
className="m-btn"
onClick={this.signup}>Submit</button>
</div>
);
}
}
Index.js(将userId作为道具传递给页面的路由):
import React, { Component } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import Home from './main/Home';
import About from './main/About';
import LoginContainer from '../components/LoginContainer';
import RegisterContainer from '../components/RegisterContainer';
import Resolved from './main/Resolved';
import Settings from './main/Settings';
export default class Routes extends Component {
render() {
return (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
<Route path="/register" render={()=> <RegisterContainer user={this.props.user} />} />
<Route path="/login" render={()=> <LoginContainer user={this.props.user} />} />
<Route path="/resolved" exact render={()=>(
this.props.user ? (<Resolved user={this.props.user} />) :
(alert("You must log in to visit this page."), (<Redirect to="/login"/>))
)} />
<Route path="/account/settings" exact render={()=>(
this.props.user ? (<Settings user={this.props.user} />) :
(alert("You must log in to visit this page."), (<Redirect to="/login"/>))
)} />
</Switch>
);
}
};
答案 0 :(得分:1)
您应该在import CareKit
import SwiftyJSON
enum ActivityType: String {
case Intervention
case Assessment
}
enum ScheduleType: String {
case Weekly
case Daily
}
enum StepFormat : String {
case Scale
case Quantity
}
protocol Activity {
var identifier : String { get set}
var groupIdentifier : String { get set}
var title : String { get set}
var colour : UIColor? { get set}
var text : String { get set}
var startDate : Date { get set}
var schedule : [NSNumber] { get set}
var scheduleType : ScheduleType { get set}
var instructions : String? { get set}
var imageURL : NSURL? { get set}
var activityType: ActivityType { get set}
var medication : Medication? { get set}
init()
init(json: JSON)
func createCareKitActivity() -> OCKCarePlanActivity
}
extension Activity {
// A mutating function to allow Acticities or Assessments to intialiser base properties
mutating func parseActivityFields(json: JSON) {
self.identifier = json["identifier"].string!
self.groupIdentifier = json["group_identifier"].string!
self.title = json["title"].string!
self.text = json["text"].string!
let colourString = json["color"].string!
self.colour = UIColor.colorWithString(colourString)
if let instructionString = json["instructions"].string {
self.instructions = instructionString
}
if let imageString = json["imageURL"].string {
let componentsOfString = imageString.components(separatedBy: ".")
if let pathForResource = Bundle.main.path(forResource: componentsOfString[0], ofType: componentsOfString[1]){
self.imageURL = NSURL(fileURLWithPath: pathForResource)
}
}
self.startDate = dateFromString(string: json["startdate"].string!)!
self.scheduleType = ScheduleType(rawValue: json["scheduletype"].string!)!
self.schedule = json["schedule"].string!.components(separatedBy: ",").map ( {
NSNumber(value: Int32($0)!)
})
if let medication = json["medication"].string,
let medicationImageString = json["medicationimage"].string {
let componentsOfString = medicationImageString.components(separatedBy: ".")
let pathForResource = Bundle.main.path(forResource: componentsOfString[0], ofType: componentsOfString[1])
self.medication = Medication.init(medication: medication, imageURL: NSURL.init(fileURLWithPath: pathForResource!))
}
}
init(json: JSON) {
self.init()
self.parseActivityFields(json: json)
}
func createCareKitActivity() -> OCKCarePlanActivity{
//creates a schedule based on the internal values for start and end dates
let startDateComponents = NSDateComponents(date: self.startDate, calendar: NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)! as Calendar)
let activitySchedule: OCKCareSchedule!
switch self.scheduleType {
case .Weekly :
activitySchedule = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents as DateComponents, occurrencesOnEachDay: self.schedule)
case .Daily:
activitySchedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents as DateComponents, occurrencesPerDay: self.schedule[0].uintValue)
}
let activity = OCKCarePlanActivity.intervention(
withIdentifier: identifier,
groupIdentifier: nil,
title: title,
text: text,
tintColor: colour,
instructions: instructions,
imageURL: imageURL as? URL,
schedule: activitySchedule,
userInfo: ["medication": medication], optional: false)
return activity
}
}
中调用Firebase连接,但不要在构造函数中调用。您可以阅读何时使用React Lifecycles的详细信息。即使它已经过时(未发表16条文章),它也是一个很棒的资源。 https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1
componentDidMount
答案 1 :(得分:0)
已解决以下问题:https://javebratt.com/firebase-user-undefined/
进行了异步调用,因为uid在获取数据之前暂时为空,并且触发了错误。只需等待数据加载就可以消除错误。另外,我正在通过fire.auth().currentUser.uid
来获取uid。
我在Settings.js中更改的代码:
componentDidMount(){
// Asynchronous call fixes uid being null on reload
fire.auth().onAuthStateChanged( user => {
if (user) {
fire.database().ref('/users/' + fire.auth().currentUser.uid).once('value').then(function(snapshot) {
this.setState({
userFirstName: (snapshot.val().userFirstName),
userLastName: (snapshot.val().userLastName),
userEmail: (snapshot.val().userEmail),
userPhone: (snapshot.val().userPhone),
userAddress: (snapshot.val().userAddress),
userZip: (snapshot.val().userZip),
userProfilePicUrl: (snapshot.val().userProfilePicUrl)
})
}.bind(this));
}
});