Неожиданный цикл рендеринга при использовании useReducer (и без useEffect) - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь встроить аутентификацию в приложение, которое я создаю. Это конкретное приложение не будет / не должно быть доступно, кроме как для пользователей в рамках конкретной аренды Microsoft Azure. По этой причине, вместо того чтобы создавать страницу входа и все ее функции, я решил просто проверить браузер пользователей на наличие действительного токена (acquTokenSilent) и, если это не удалось, дать им всплывающее окно для входа в систему. Однако после того, как я установил правильную аутентификацию, я обнаружил, что приложение постоянно обновляется.

С тех пор я создал кодовую коробку без осложнений MSAL и получаю точно такое же поведение .

Я новичок в редукторах, но я не думал, что повторное рендеринг произойдет, если состояние не изменится. Я обнаружил похожую проблему , но это зависит от использования useEffect для воспроизведения, которое я сейчас не использую. Где я неправильно понимаю, как все работает?

/ auth.js

export default class Auth {
  constructor() {
    this.handleAuthentication = this.handleAuthentication.bind(this);
  }
  getProfile() {
    return {
      username: "FakeUser",
      name: "John Doe",
      email: "jd@fakeusers.net"
    };
  }

  handleAuthentication() {
    return new Promise(resolve => {
      console.log("handle Authentication function hit");
      //fake auth
      setTimeout(() => {
        console.log("timeout occurred, resolving.");
        resolve();
      }, 1000);
    });
  }
}

/ AuthApp.js

import React, { useReducer, createContext } from "react";
import Auth from "./auth.js";

const auth = new Auth();
const UserContext = createContext();

const initialState = {
  auth: false,
  user: null
};

const reducer = (state, action) => {
  console.log("reducer hit!", action);
  switch (action.type) {
    case "loginUser":
      console.log(action.payload);
      return {
        ...state,
        isAuthenticated: action.payload.authenticated,
        userProfile: action.payload.user
      };
    default:
      console.log("Reducer hit without a payload!", action);
      return state;
  }
};

const UserContextProvider = props => {
  console.log("UserContextProvider Element rendering...");
  const [state, dispatch] = useReducer(reducer, initialState.user);
  auth.handleAuthentication().then(() => {
    dispatch({
      type: "loginUser",
      payload: {
        authenticated: true,
        user: auth.getProfile()
      }
    });
  });
  return (
    <UserContext.Provider
      value={{
        ...state
      }}
    >
      {props.children}
    </UserContext.Provider>
  );
};

const App = () => {
  return (
    <UserContextProvider>
      <UserContext.Consumer>
        {user =>
          user.isAuthenticated ? (
            <div>{JSON.stringify(user)}</div>
          ) : (
            <div>You are not logged in.</div>
          )
        }
      </UserContext.Consumer>
    </UserContextProvider>
  );
};

1 Ответ

0 голосов
/ 25 октября 2019

Часть, которой не хватало, заключалась в том, что здесь требуется useEffect или useMemo. Вам нужно проверить, требуется ли дополнительная аутентификация, а не просто наличие ее в функции, как в конструкторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...