【问题标题】:How to implement Firebase authentication with React Redux?如何使用 React Redux 实现 Firebase 身份验证?
【发布时间】: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 时。如何让商店更新?

【问题讨论】:

    标签: reactjs facebook firebase react-redux


    【解决方案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);
    

    我希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2018-01-02
      • 1970-01-01
      • 2017-12-29
      • 2017-11-29
      • 2017-05-10
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 2020-06-02
      相关资源
      最近更新 更多