如何使用React Redux实施Firebase身份验证? [英] How to implement Firebase authentication with React Redux?

查看:63
本文介绍了如何使用React Redux实施Firebase身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firebase通过Facebook或google处理我的身份验证.我真正不明白的是我的商店未更新的原因.

I am using Firebase to handle my authentication through Facebook or google. The thing I really do not understand is the reason why is my store not updated.

下面是我的代码示例:

import { createStore } from 'redux';
import {app, facebookProvider, googleProvider } from './../config/config';

const initialState = {
    SCREEN_CURRENT: "login",
    authenticated: false
}

const reducer = (state = initialState, action) => {
console.log('reducer', action);

switch(action.type){
    case "AUTH_LOGIN_FACEBOOK":
        state = {
            ...state,
            authenticated: true
        }

        app.auth().signInWithPopup(facebookProvider)
        .then((user, error) => {
            if(error){
                console.log("Unable to login with Facebook!");
            } else {
                console.log("Logged in succesfully");
                state = Object.assign({}, state, {
                    authenticated: true
                });
            }
        }).catch((error) => {
            if(error){
                console.log("Error from Facebook: " + error.message);
            }
        });
        break;

    case "AUTH_LOGIN_GOOGLE":
        app.auth().signInWithPopup(googleProvider)
        .then((user, error) => {
            if(error){
                console.log("Unable to login with Google!");
            } else {
                console.log("Logged in succesfully");
                return Object.assign({}, state, {
                    authenticated: true
                });
            }
        }).catch((error) => {
            if(error){
                console.log("Error from Google: " + error.message);
            }
        });
        break;

    default:
        break;
}

return state;
}

const store = createStore(reducer);

store.subscribe(() => {
    console.log("Store updated", store.getState());
});

export default store;

即使我在成功登录后将身份验证状态更改为true(发生了情况),有人可以解释我为什么不更新我的商店吗?

Can someone explain me why my store is not updated, even though I change my authentication state to true on succesful login (which happened)?

我不明白为什么.

当我单击触发"AUTH_LOGIN_FACEBOOK"操作的按钮时,商店将得到更新.但是,当我将authenticated的状态更改为true时,不是这样.如何获取商店更新?

When I click the button that triggers the "AUTH_LOGIN_FACEBOOK" action, the store gets updated. However, not when I change the state of authenticated to true. How do I get the store to update?

推荐答案

Reducer内部逻辑太多.这里要做的第一件事是将它们移至一个动作,一个普通的旧javascript对象,甚至一个函数.请注意,上面的代码没有考虑导入/导出,但是我想您会在这里理解我的意思.因此,您必须使其适应您的用例.

There's too much logic inside the reducer. First thing to do here is to move them to an action, or a plain old javascript object, or even a function. Please notice that the code above doesn't take import/export into account, but I think you'll get my point here. Therefore, you have to adapt it to your use case.

// ##########################################################################
// AUTH FUNCTIONS ###########################################################
// ##########################################################################

const FACEBOOK = 'facebook';
const GOOGLE = 'google';

// just to make sure that you'll always return a valid prodiver.
function getProviderObject(provider) {
  return {
    [FACEBOOK]: new firebase.auth.FacebookAuthProvider(),
    [GOOGLE]: new firebase.auth.GoogleAuthProvider()
  }[provider] || null;
}

// this function receives a provider object and return a User, no matter what
// provider, Google or Facebook
function signInWithProvider(provider) {  
  const providerObject = getProviderObject(provider);

  if(!providerObject) {
    throw new Error('Invalid provider');
  }

  try {
    const response = await FirebaseApp.auth().signInWithPopup(provider);

    return response.user;
  } catch(error) {
    // handle error...
    throw error;
  }
}

function signInWithFirebase({ email, password }) {
  return FirebaseApp.auth().signInAndRetrieveDataWithEmailAndPassword(email, password);
}


// ##########################################################################
// ACTIONS ##################################################################
// ##########################################################################

// this action acts like a router, which will decide to sign in with an 
// external provider (GOOGLE or FACEBOOK) or sign in with email/password
const signIn = param => async dispatch => {
  try {
    const user = await (
      [GOOGLE, FACEBOOK].includes(param) ?
        signInWithProvider(param) :
        signInWithFirebase(param)
    );

    dispatch({
      type: 'CREATE_SESSION',
      payload: user
    });

    return user;
  } catch(error) {
    console.log(error);
  }
};

// ##########################################################################
// REDUCERS #################################################################
// ##########################################################################

const initialState = { 
  authenticated: false, 
  user: null,
  // etc...
};

function sessionReducer(state = initialState, action = {}) {
  switch(action.type) {
    case 'CREATE_SESSION': return { 
      ...action.payload, 
      authenticated: true,
      // whatever props you need here...
    };

    case 'DESTROY_SESSION': return initialState;

    default: return state;
  }
}

// ##########################################################################
// EXAMPLE ##################################################################
// ##########################################################################

class Auth extends React.Component {
  state = {
    email: null,
    password: null
  };

  render() {
    const { email, password } = this.state;

    return (
      <p><a href="#" onClick={this.signInWith(FACEBOOK))>SIGN IN WITH FACEBOOK</a></p>
      <p><a href="#" onClick={this.signInWith(GOOGLE))>SIGN IN WITH GOOGLE</a></p>

      <form onSubmit={this.onSubmit}>
        <input 
          type="email" 
          onChange={this.onChange('email')} 
          value={email} placeholder="Email" 
        />

        <input 
          type="password" 
          onChange={this.onChange('email')} 
          value={password} 
          placeholder="Password" 
        />

        <button>Sign In</button>
      </form>
    )
  }

  signInWith = provider => event => {
    event.preventDefault();
    this.props.signIn(provider);
  }

  onChange = field => value => this.setState({ [field]: value });

  onSubmit = () => {
    const { email, password } = this.state;
    return this.props.signIn({ email, password });
  };
}

export default connect(null, { signIn })(Auth);

我希望这会有所帮助!

这篇关于如何使用React Redux实施Firebase身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆