Я пытаюсь заставить мой navbar динамически показывать разные вещи в зависимости от того, вошел ли пользователь в систему или нет, используя React и Redux. И на самом деле, это оказалось управляемым, я подключил создателей действий, которые проверяют, существует ли пользовательский объект и, если есть, то переключают свойство isSignedIn в true и показывают содержимое соответствующим образом.
Сложность заключалась в том, что я хочу показать фотографию профиля этого пользователя и в навигационной панели. Чтобы сделать это, мой план состоял в том, чтобы создатель действия запустил функцию, которая получит документы пользователя из базы данных (firebase) и вернет детали в состоянии компоненту navbar. Затем mapStateToProps возьмет этот контент и переместит его в подпорки, чтобы я мог манипулировать ими в представлении пользователей.
Я могу заставить все это работать до определенного момента, компонент запускается, и требуется немного времени, чтобы получить информацию о пользователях из firebase, поэтому есть пара секунд, когда свойство props.user пусто , Это нормально, но когда он возвращается с пользовательским контентом, они сохраняются в объекте в массиве, и я понятия не имею, как получить к ним доступ.
Итак, this.props.user - это массив с одним объектом, который имеет пары ключ-значение, такие как userDateOfBirth: «12-12-2020» и так далее. Мне нужно получить доступ к этим ценностям. Я думал, что this.props.user.userDateOfBirth или this.props.user [0] .userDateOfBirth будет работать, но не работает. Первый просто возвращает «undefined», а второй возвращает ошибку «Не удается прочитать свойство 'userDateOfBirth' undefined.
Пожалуйста, помогите, это сводит меня с ума.
Я обновил вопрос чтобы включить некоторый код, который должен сделать это немного более понятным. Я оставил функцию рендеринга из компонента navbar для краткости.
Создатели Action SignIn и SignOut работают, как я и ожидал. Это CurrentUser Action Creator, с которым у меня возникают трудности. Я поделился тем, что считаю необходимым, и, может быть, слишком много. Спасибо за любую помощь.
Код ниже:
* Компонент Navbar *
import './NavBar.css';
import {Link} from "react-router-dom";
import React from "react";
import {connect} from "react-redux";
import * as firebase from "firebase";
import {signedIn, signedOut, currentUser} from "../actions";
componentDidMount()
{
this.unregisterAuthObserver = firebase.auth().onAuthStateChanged((user) => {
let currentUser = user;
if (user) {
this.props.signedIn()
} else this.props.signedOut();
if (this.props.auth.isSignedIn) {
this.props.currentUser(currentUser.uid);
}
});
}
render() {
return (
this.props.auth.isSignedIn ?
//If the user is signed in, show this version of the navbar
//Overall NavBar
<div id="navBar">
{/*Left side of the NavBar*/}
<div id="navBarLeft">
<Link to ={"/"}
>
{/* OLAS Logo*/}
<img
alt={"Olas Logo"}
id="logo"
src={require("../img/Olas_Logo&Brandmark_White.png")}
/>
</Link>
</div>
{/*Right side of the NavBar*/}
<div id="navBarRight">
<div id="home" className="navBarItem">
<Link to={"/"} >
HOME
</Link>
</div>
<div id="careerPaths" className="navBarItem">
<Link to={"/careerPath"} >
CAREER PATHS
</Link>
</div>
<div id="jobPostInsights" className="navBarItem">
<Link to={"/jobPostInsights"} >
JOB POST INSIGHTS
</Link>
</div>
<div id="careerQ&AForum" className="navBarItem">
<Link to={"/forum"} >
CAREER Q&A FORUM
</Link>
</div>
<div id="userProfile" className="navBarItem">
<Link to={"/userprofile"}>
{this.props.user.length ? (<div>{this.props.user.user[0].userFirstName}</div>): <div>PROFILE</div>}
</Link>
</div>
</div>
</div>
//This is a critical part of the ternary operator - DO NOT DELETE
:
//If the user is not signed in, show this version of the navbar
<div id="navBar">
{/*Left side of the NavBar*/}
<div id="navBarLeft">
<Link to ={"/"}
>
{/* OLAS Logo*/}
<img
alt={"Olas Logo"}
id="logo"
src={require("../img/Olas_Logo&Brandmark_White.png")}
/>
</Link>
</div>
{/*Right side of the NavBar*/}
<div id="navBarRight">
<div/>
<div/>
<div id="about" className="navBarItem">
<Link to={"about"}>
<span className="navBarItemInner">ABOUT OLAS</span>
</Link>
</div>
<div id="home" className="navBarItem">
<Link to={"/"} >
<span className="navBarItemInner">HOME</span>
</Link>
</div>
<div id="signIn" className="navBarItem" >
<Link to={"/signIn"} >
<span className="navBarItemInner">SIGN IN / REGISTER</span>
</Link>
</div>
</div>
</div>
)};
const mapStateToProps = state => {
console.log(state);
return {auth: state.auth, user: state.user}
};
export default connect(mapStateToProps, {signedIn, signedOut, currentUser})(NavBar);
* currentUser Action Creator *
export const currentUser = (currentUserUid) => {
return async (dispatch) => {
const response = await getUserDocFromDB(currentUserUid);
dispatch({
type: GET_CURRENT_USER,
payload: response,
});
}
};
* getUserDocFromDB *
import getFirestoreDb from '../getFirestoreDb';
let db = getFirestoreDb();
const getUserDocFromDB = async (currentUserUid) => {
let userDoc = [];
await
db.collection("users")
.where("userFirebaseUid", "==", currentUserUid)
.onSnapshot(
(querySnapshot) => {
if (querySnapshot.empty) {
return;
}
querySnapshot.forEach((doc) => {
const {
userDateOfBirth,
userGender,
userState,
userCity,
userTitle,
userDescription,
userFirstName,
userLastName,
userProfileImageUrl,
} = doc.data();
userDoc.push({
userDateOfBirth,
userGender,
userState,
userCity,
userTitle,
userDescription,
userFirstName,
userLastName,
});
});
},
function(error) {
console.log("Error getting document Error: ", error);
},
);
return userDoc;
};
export default getUserDocFromDB;
* Редуктор пользователя *
import {GET_CURRENT_USER} from "../actions/ActionTypes";
const INITIAL_STATE = {
user: null,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case GET_CURRENT_USER:
return {user: action.payload};
default:
return INITIAL_STATE;
}
};
* Комбинированные редукторы *
import { combineReducers } from "redux";
export default combineReducers({
user: UserReducer,
});