如何使用 React Redux 实现 Firebase 身份验证?

Posted

技术标签:

【中文标题】如何使用 React Redux 实现 Firebase 身份验证?【英文标题】:How to implement Firebase authentication with React Redux? 【发布时间】:2019-03-25 07:30:12 【问题描述】:

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

下面是我的代码示例:

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(发生了这种情况)?

我不明白为什么。

当我单击触发“AUTH_LOGIN_FACEBOOK”操作的按钮时,商店会更新。但是,不是当我将身份验证的状态更改为 true 时。如何让商店更新?

【问题讨论】:

【参考方案1】:

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

// ##########################################################################
// 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 身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React、Redux 和 Webpack 实现 Google API

如何使用 React Redux 发出 post 请求?

如何使用 Redux 在 React Native 中使用线程调用 API?

如何使用 thunk 和 useDispatch(react-redux 挂钩)从操作中返回承诺?

如何使用 react-redux 将错误 500 全局重定向到页面

Redux 基础教程以及结合 React 使用方式