Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 正在从firebase实时数据库用户集合中丢失数据属性_Reactjs_Firebase_Firebase Realtime Database_Firebase Authentication - Fatal编程技术网

Reactjs 正在从firebase实时数据库用户集合中丢失数据属性

Reactjs 正在从firebase实时数据库用户集合中丢失数据属性,reactjs,firebase,firebase-realtime-database,firebase-authentication,Reactjs,Firebase,Firebase Realtime Database,Firebase Authentication,我知道这个问题在其他场合也有人问过。我读过这些答案。我试过答案了。我已经通读了firebase的文档。到目前为止,这没有帮助。我是firebase的新手。通过一起使用React和Firebase的教程学习如何使用该产品。为用户构建身份验证/授权模块。可以成功注册/注册用户,并在firebase项目概述的授权模块和实时数据库中查看结果。当用户注销时,对RDb的检查确认所有数据属性都保持不变。当用户再次登录(电子邮件/密码)时,对RDb的检查显示只有uid和电子邮件地址保留在RDb中。用户名和角色等

我知道这个问题在其他场合也有人问过。我读过这些答案。我试过答案了。我已经通读了firebase的文档。到目前为止,这没有帮助。我是firebase的新手。通过一起使用React和Firebase的教程学习如何使用该产品。为用户构建身份验证/授权模块。可以成功注册/注册用户,并在firebase项目概述的授权模块和实时数据库中查看结果。当用户注销时,对RDb的检查确认所有数据属性都保持不变。当用户再次登录(电子邮件/密码)时,对RDb的检查显示只有uid和电子邮件地址保留在RDb中。用户名和角色等用户的非身份验证属性变为空字符串或对象,存在但未填充。我已经阅读了相当多的firebase文档并调试了代码,但我无法确定为什么会发生这种情况,因此无法确定如何修复它

以下是一些代码段:

首先是firebase模块:

import app from 'firebase/app'
import 'firebase/auth'
import 'firebase/database'

... set up the config ...

// set the config constant to the appropriate value
const config = process.env.NODE_ENV === 'production' ? prodConfig : devConfig

class Firebase {
  constructor() {
    // initialize the app using the Firebase config to instatiate all of the firebase services
    app.initializeApp(config)

    // instantiate the initial auth state within the app
    this.auth = app.auth()  // Gets the Auth service for the current app

    // instantiate the database within the app
    this.db = app.database()  // Gets the Database service for the current app
    console.log('this.db ', this.db)

    // Social media login providers (authorization methods within Firebase)
    this.googleProvider = new app.auth.GoogleAuthProvider()
    this.facebookProvider = new app.auth.FacebookAuthProvider()
    this.twitterProvider = new app.auth.TwitterAuthProvider()
  }

  ... the comments are mostly for my benefit ...

  // ***** Firebase Auth API *****
  // create user with email and password (equate doCreate... with Firebase createUser...)
  doCreateUserWithEmailAndPassword = ( email, password ) => this.auth.createUserWithEmailAndPassword( email, password )
  // ***** SignIn with email ***** (equate doSignIn... with Firebase signIn...)
  doSignInWithEmailAndPassword = ( email, password ) => this.auth.signInWithEmailAndPassword( email, password )
  // ***** SignIn with facebook ***** (equate as above)
  doSignInWithFacebook = () => this.auth.signInWithPopup( this.facebookProvider )
  // ***** SignIn with google ***** (equate as above)
  doSignInWithGoogle = () => this.auth.signInWithPopup( this.googleProvider )
  // ***** SignIn with twitter ***** (equate as above)
  doSignInWithTwitter = () => this.auth.signInWithPopup( this.twitterProvider )
  // ***** SignOut ***** (equate as above)
  doSignOut = () => this.auth.signOut()
  // ***** Password Reset ***** (equate as above)
  doPasswordReset = email => this.auth.sendPasswordResetEmail( email )
  // ***** Password Update ***** (equate as above)
  doPasswordUpdate = password => this.auth.currentUser.updatePassword( password )

  // ***** User API ***** 
  // set the current user id
  user = uid => this.db.ref(`users/${uid}`)
  // set the reference to the users collection in the firebase database
  users = () =>this.db.ref('users')

  // ***** Merge Auth and DB User API *****

  ... big block of comments to me ...

  onAuthUserListener = (next, fallback) =>
    this.auth.onAuthStateChanged(authUser => {  
      if ( authUser ) {                         
        this.user(authUser.uid)                 
          .once('value')                        
          .then(snapshot => {                          
            const dbUser = snapshot.val()
            console.log('this.user ',this.user)    
            console.log('dbUser ',dbUser)
            // default empty roles
            if ( !dbUser.roles ) {
              dbUser.roles = {}
            }
            // merge auth and db user
            this.db.ref(`users/${this.user}`).set({
              uid: authUser.uid,
              email: authUser.email,
              username: authUser.username,
              roles: authUser.roles,
              ...dbUser,
            })
            console.log('firebase.js authUser ', authUser)
            next(authUser)
          })
      } else {                                  //  there is no authUser
        fallback()
      }
    })
}

export default Firebase
以下是注册组件:

// index.js - SignUp
//  the entry point for the SignUp component
import React, { Component } from 'react'
import { Link, withRouter } from 'react-router-dom'
import { compose } from 'recompose'

import { Typography, Input, Checkbox, FormLabel, Button } from '@material-ui/core'

import { withFirebase } from '../Firebase'
import * as ROUTES from '../../constants/routes'
import * as ROLES from '../../constants/roles'

import '../../styles/auth.css'

const SignUpPage = () => (
  <div id='wrapper' className='signup-page'>
    <SignUpForm />
  </div>
)

// initialize the state of the component using destructuring
// allows INITIAL_STATE to be reset after successful SignUp
const INITIAL_STATE = {
  username: '',
  email: '',
  passwordOne: '',
  passwordTwo: '',
  isAdmin: false,
  error: null,
}

class SignUpFormBase extends Component {
  constructor(props) {
    super(props)

    // spread operator (...) spreads out to reach all properties individually
    this.state = { ...INITIAL_STATE }
  }

  onSubmit = event => {
    // get necessary info from this.state to pass to the Firebase authentication API
    const { username, email, passwordOne, isAdmin } = this.state
    const roles = {}
    if ( isAdmin ) { roles[ROLES.ADMIN] = ROLES.ADMIN } //  set roles if the admin checkbox is checked

    this.props.firebase
      // create a user (limited access) in the authentication database
      .doCreateUserWithEmailAndPassword( email, passwordOne )
      // successful 
      .then( authUser => {
        // create a user in Firebase realtime database -- this is where you manage user properties
        // because in the firebase auth module, users cannot be manipulated.
        console.log('signup authUser ',authUser)
        return this.props.firebase
          .user(authUser.user.uid)          //  use the authUser.uid to:
          .set({ username, email, roles })  //  write username, email & roles to the rdb
      })
      .then(() => {
        // update state and redirect to Home page
        this.setState({ ...INITIAL_STATE })
        this.props.history.push(ROUTES.HOME)
      })
      // error - setState, error (if something is wrong)
      .catch(error => {
        this.setState({ error })
      })
    // prevent default behavior (a reload of the browser)
    event.preventDefault()
  }

  onChange = event => {
    // dynamically set state properties when they change, based on which input call is executed
    // each <input> element (in the return) operates on a different property of state (according to value)
    this.setState({ [event.target.name]: event.target.value })
  }

  onChangeCheckbox = event => {
    this.setState({ [event.target.name]: event.target.checked })
  }

  render() {
    // parse each of the values from current state
    const {
      username,
      email,
      passwordOne,
      passwordTwo,
      isAdmin,
      error
    } = this.state
    // list of invalid conditions for which to check (validation of form elements)
    const isInvalid =
      passwordOne !== passwordTwo ||
      passwordOne === '' ||
      email === '' ||
      username === ''
    return (
      // the input form -- with fields (username, email, passwordOne, passwordTwo)
      <div className='container'>
        <Typography 
          variant='h6' 
          align = 'center' 
          className='item'
        >
          Sign Up Page
        </Typography>
        <br />
        <form className='signup-form item' onSubmit={ this.onSubmit }>
          <Input
            className='item'
            name='username'
            value={username}
            onChange={this.onChange}
            type='text'
            placeholder='Full Name'
          />

... input email, password, confirm password, checkbox to designate Admin ...

          <Button
            variant='contained'
            className='item btn btn-secondary' 
            disabled={ isInvalid } 
            type='submit'
          >
            Sign Up
          </Button>

          {/* if there is an error (a default Firebase property), render the error message */}
          {error && <p>{ error.message }</p>}
        </form>
      </div>
    )
  }
}

const SignUpLink = () => (
  <Typography 
    variant = 'body1' 
    align = 'center' 
    className = 'item' 
  >
    Don't have an account? <Link to={ ROUTES.SIGN_UP }>Sign Up</Link>
  </Typography>
)

const SignUpForm = compose(withRouter, withFirebase)(SignUpFormBase)

export default SignUpPage

export { SignUpForm, SignUpLink }
// SignInEmail.js - SignIn
//  the email/password SignIn component
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'

import { Typography, Input } from '@material-ui/core'
import Button from 'react-bootstrap/Button'

import { withFirebase } from '../Firebase'
import * as ROUTES from '../../constants/routes'

// initialize the state of the component using destructuring
// allows INITIAL_STATE to be reset after successful SignUp
const INITIAL_STATE = {
  username: '',
  email: '',
  password: '',
  roles: {},
  error: null,
}

// ======================================
// ***** signin with email/password *****
// ======================================
class SignInEmailBase extends Component {
  constructor(props) {
    super(props)

    // spread operator (...) spreads out to reach all properties individually
    this.state = {
      ...INITIAL_STATE
    }
  }

  onSubmit = event => {
    // get necessary info from this.state to pass to the Firebase authentication API
    // const { username, email, password, roles } = this.state
    const { username, email, password, roles } = this.state

    this.props.firebase
      // execute SignIn function (create a user)
      .doSignInWithEmailAndPassword( email, password )
      // successful 
      .then(authUser => {
        // create a user in Firebase Realtime database
        console.log('signin authUser ',authUser)
        return this.props.firebase
          .user(authUser.user.uid)
          .set({ username, email, roles })
      })
      .then(() => {
        // update state and redirect to Home page
        this.setState({ ...INITIAL_STATE })
        this.props.history.push(ROUTES.HOME)
      })
      // error - setState, error (if something is wrong)
      .catch(error => {
        this.setState({
          error
        })
      })
    // prevent default behavior (a reload of the browser)
    event.preventDefault()
  }

  onChange = event => {
    // dynamically set state properties when they change, based on which input call is executed
    // each <input> element (in the return) operates on a different property of state (according to value)
    this.setState({ [event.target.name]: event.target.value })
  }

  render() {
    // parse each of the values from current state
    const { email, password, error } = this.state

    // list of invalid conditions for which to check (validation of form elements)
    const isInvalid = password === '' || email === ''

    return (
      // the input form -- with fields (username, email, passwordOne, passwordTwo)
      <div className = 'container signin-page'>
        <Typography 
          variant = 'h6' 
          align = 'center' 
          className = 'item' 
        >
          Sign In Page
        </Typography> 
        <br />
        <form className = 'item email-form' onSubmit = { this.onSubmit} >

          ... input email, password...

          { /* disable the button if the form is invalid -- see isInvalid above */ } 
          <Button 
            className = 'item btn btn-secondary' 
            type = 'submit' 
            disabled = { isInvalid } 
          >
            SIGN IN WITH EMAIL
          </Button>

          { /* if there is an error (a default Firebase property), render the error message */ }
          { error && <p> { error.message } </p> } 
        </form>
      </div>
    )
  }
}

const SignInEmail = compose(withRouter, withFirebase, )(SignInEmailBase)

export default SignInEmail
//index.js-注册
//注册组件的入口点
从“React”导入React,{Component}
从“react router dom”导入{Link,withRouter}
从“重新组合”导入{compose}
从“@material ui/core”导入{排版、输入、复选框、表单标签、按钮}
从“../Firebase”导入{withFirebase}
从“../../constants/ROUTES”导入*作为路由
从“../../constants/ROLES”导入*作为角色
导入“../styles/auth.css”
const SignUpPage=()=>(
)
//使用分解结构初始化组件的状态
//允许在成功注册后重置初始_状态
常量初始状态={
用户名:“”,
电子邮件:“”,
密码一:“”,
密码2:“”,
伊萨明:错,
错误:null,
}
类SignUpFormBase扩展组件{
建造师(道具){
超级(道具)
//展开运算符(…)展开以分别到达所有属性
this.state={…初始状态}
}
onSubmit=事件=>{
//从this.state获取必要信息以传递给Firebase身份验证API
const{username,email,passwordOne,isAdmin}=this.state
常量角色={}
if(isAdmin){roles[roles.ADMIN]=roles.ADMIN}//选中ADMIN复选框时设置角色
这是消防基地
//在身份验证数据库中创建用户(受限访问)
.doCreateUserWithEmailAndPassword(电子邮件、passwordOne)
//成功的
。然后(authUser=>{
//在Firebase实时数据库中创建用户--这是管理用户属性的地方
//因为在firebase身份验证模块中,无法操纵用户。
console.log('signup authUser',authUser)
归还这个.props.firebase
.user(authUser.user.uid)//使用authUser.uid:
.set({username,email,roles})//将username,email和roles写入rdb
})
.然后(()=>{
//更新状态并重定向到主页
this.setState({…初始状态})
这个。道具。历史。推送(路线。主页)
})
//错误-设置状态,错误(如果出现错误)
.catch(错误=>{
this.setState({error})
})
//防止默认行为(重新加载浏览器)
event.preventDefault()
}
onChange=事件=>{
//根据执行的输入调用,在状态属性更改时动态设置状态属性
//每个元素(在返回中)在不同的状态属性上运行(根据值)
this.setState({[event.target.name]:event.target.value})
}
onChangeCheckbox=事件=>{
this.setState({[event.target.name]:event.target.checked})
}
render(){
//从当前状态解析每个值
常数{
用户名,
电子邮件,
密码一,
密码二,
伊萨明,
错误
}=这个州
//要检查的无效条件列表(表单元素的验证)
康斯特·伊森瓦利德=
密码一!==密码二||
passwordOne==''||
电子邮件==''||
用户名==''
返回(
//输入表单--带有字段(用户名、电子邮件、密码一、密码二)
注册页面

…输入电子邮件、密码、确认密码、复选框以指定管理员。。。 注册 {/*如果出现错误(默认Firebase属性),则呈现错误消息*/} {error&{error.message}

} ) } } 常量符号上行链路=()=>( 没有帐户?注册吧 ) const SignUpForm=compose(带路由器,带Firebase)(SignUpFormBase) 导出默认签名 导出{SignUpForm,SignUpLink}
以下是登录(电子邮件/密码)组件:

// index.js - SignUp
//  the entry point for the SignUp component
import React, { Component } from 'react'
import { Link, withRouter } from 'react-router-dom'
import { compose } from 'recompose'

import { Typography, Input, Checkbox, FormLabel, Button } from '@material-ui/core'

import { withFirebase } from '../Firebase'
import * as ROUTES from '../../constants/routes'
import * as ROLES from '../../constants/roles'

import '../../styles/auth.css'

const SignUpPage = () => (
  <div id='wrapper' className='signup-page'>
    <SignUpForm />
  </div>
)

// initialize the state of the component using destructuring
// allows INITIAL_STATE to be reset after successful SignUp
const INITIAL_STATE = {
  username: '',
  email: '',
  passwordOne: '',
  passwordTwo: '',
  isAdmin: false,
  error: null,
}

class SignUpFormBase extends Component {
  constructor(props) {
    super(props)

    // spread operator (...) spreads out to reach all properties individually
    this.state = { ...INITIAL_STATE }
  }

  onSubmit = event => {
    // get necessary info from this.state to pass to the Firebase authentication API
    const { username, email, passwordOne, isAdmin } = this.state
    const roles = {}
    if ( isAdmin ) { roles[ROLES.ADMIN] = ROLES.ADMIN } //  set roles if the admin checkbox is checked

    this.props.firebase
      // create a user (limited access) in the authentication database
      .doCreateUserWithEmailAndPassword( email, passwordOne )
      // successful 
      .then( authUser => {
        // create a user in Firebase realtime database -- this is where you manage user properties
        // because in the firebase auth module, users cannot be manipulated.
        console.log('signup authUser ',authUser)
        return this.props.firebase
          .user(authUser.user.uid)          //  use the authUser.uid to:
          .set({ username, email, roles })  //  write username, email & roles to the rdb
      })
      .then(() => {
        // update state and redirect to Home page
        this.setState({ ...INITIAL_STATE })
        this.props.history.push(ROUTES.HOME)
      })
      // error - setState, error (if something is wrong)
      .catch(error => {
        this.setState({ error })
      })
    // prevent default behavior (a reload of the browser)
    event.preventDefault()
  }

  onChange = event => {
    // dynamically set state properties when they change, based on which input call is executed
    // each <input> element (in the return) operates on a different property of state (according to value)
    this.setState({ [event.target.name]: event.target.value })
  }

  onChangeCheckbox = event => {
    this.setState({ [event.target.name]: event.target.checked })
  }

  render() {
    // parse each of the values from current state
    const {
      username,
      email,
      passwordOne,
      passwordTwo,
      isAdmin,
      error
    } = this.state
    // list of invalid conditions for which to check (validation of form elements)
    const isInvalid =
      passwordOne !== passwordTwo ||
      passwordOne === '' ||
      email === '' ||
      username === ''
    return (
      // the input form -- with fields (username, email, passwordOne, passwordTwo)
      <div className='container'>
        <Typography 
          variant='h6' 
          align = 'center' 
          className='item'
        >
          Sign Up Page
        </Typography>
        <br />
        <form className='signup-form item' onSubmit={ this.onSubmit }>
          <Input
            className='item'
            name='username'
            value={username}
            onChange={this.onChange}
            type='text'
            placeholder='Full Name'
          />

... input email, password, confirm password, checkbox to designate Admin ...

          <Button
            variant='contained'
            className='item btn btn-secondary' 
            disabled={ isInvalid } 
            type='submit'
          >
            Sign Up
          </Button>

          {/* if there is an error (a default Firebase property), render the error message */}
          {error && <p>{ error.message }</p>}
        </form>
      </div>
    )
  }
}

const SignUpLink = () => (
  <Typography 
    variant = 'body1' 
    align = 'center' 
    className = 'item' 
  >
    Don't have an account? <Link to={ ROUTES.SIGN_UP }>Sign Up</Link>
  </Typography>
)

const SignUpForm = compose(withRouter, withFirebase)(SignUpFormBase)

export default SignUpPage

export { SignUpForm, SignUpLink }
// SignInEmail.js - SignIn
//  the email/password SignIn component
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'

import { Typography, Input } from '@material-ui/core'
import Button from 'react-bootstrap/Button'

import { withFirebase } from '../Firebase'
import * as ROUTES from '../../constants/routes'

// initialize the state of the component using destructuring
// allows INITIAL_STATE to be reset after successful SignUp
const INITIAL_STATE = {
  username: '',
  email: '',
  password: '',
  roles: {},
  error: null,
}

// ======================================
// ***** signin with email/password *****
// ======================================
class SignInEmailBase extends Component {
  constructor(props) {
    super(props)

    // spread operator (...) spreads out to reach all properties individually
    this.state = {
      ...INITIAL_STATE
    }
  }

  onSubmit = event => {
    // get necessary info from this.state to pass to the Firebase authentication API
    // const { username, email, password, roles } = this.state
    const { username, email, password, roles } = this.state

    this.props.firebase
      // execute SignIn function (create a user)
      .doSignInWithEmailAndPassword( email, password )
      // successful 
      .then(authUser => {
        // create a user in Firebase Realtime database
        console.log('signin authUser ',authUser)
        return this.props.firebase
          .user(authUser.user.uid)
          .set({ username, email, roles })
      })
      .then(() => {
        // update state and redirect to Home page
        this.setState({ ...INITIAL_STATE })
        this.props.history.push(ROUTES.HOME)
      })
      // error - setState, error (if something is wrong)
      .catch(error => {
        this.setState({
          error
        })
      })
    // prevent default behavior (a reload of the browser)
    event.preventDefault()
  }

  onChange = event => {
    // dynamically set state properties when they change, based on which input call is executed
    // each <input> element (in the return) operates on a different property of state (according to value)
    this.setState({ [event.target.name]: event.target.value })
  }

  render() {
    // parse each of the values from current state
    const { email, password, error } = this.state

    // list of invalid conditions for which to check (validation of form elements)
    const isInvalid = password === '' || email === ''

    return (
      // the input form -- with fields (username, email, passwordOne, passwordTwo)
      <div className = 'container signin-page'>
        <Typography 
          variant = 'h6' 
          align = 'center' 
          className = 'item' 
        >
          Sign In Page
        </Typography> 
        <br />
        <form className = 'item email-form' onSubmit = { this.onSubmit} >

          ... input email, password...

          { /* disable the button if the form is invalid -- see isInvalid above */ } 
          <Button 
            className = 'item btn btn-secondary' 
            type = 'submit' 
            disabled = { isInvalid } 
          >
            SIGN IN WITH EMAIL
          </Button>

          { /* if there is an error (a default Firebase property), render the error message */ }
          { error && <p> { error.message } </p> } 
        </form>
      </div>
    )
  }
}

const SignInEmail = compose(withRouter, withFirebase, )(SignInEmailBase)

export default SignInEmail
//SignInEmail.js-SignIn
//电子邮件/密码登录组件
从“React”导入React,{Component}
从“react router dom”导入{withRouter}
从“重新组合”导入{compose}
从“@material ui/core”导入{排版,输入}
从“反应引导/按钮”导入按钮
从“../Firebase”导入{withFirebase}
从“../../constants/ROUTES”导入*作为路由
//使用分解结构初始化组件的状态
//允许在成功注册后重置初始_状态
常量初始状态={
用户名:“”,
电子邮件:“”,
密码:“”,
角色:{},
错误:null,
}
// ======================================
//******使用电子邮件/密码登录*****
// ======================================
类SignInEmailBase扩展组件{
建造师(道具){
超级(道具)
//展开运算符(…)展开以分别到达所有属性
此.state={
…初始状态
}
}
onSubmit=事件=>{
//从this.state获取必要的信息以传递给Fireba