I have React Components:
My account.jsx
import "./myAccount.sass";
import { auth } from "../../firebaseConfig";
import {
signOut,
onAuthStateChanged,
} from "https://www.gstatic.com/firebasejs/9.6.0/firebase-auth.js";
import { useEffect, useState } from "react";
import { Hotel } from "../Hotel/Hotel";
function MyAccount(props) {
const { isauth } = props;
const { hotels = [] } = props;
const [userEmail, setUserEmail] = useState([]);
function logout() {
signOut(auth);
isauth(false);
console.log("Successful logout");
}
function userInfo() {
onAuthStateChanged(auth, (user) => {
console.log(`user info: ${user.email}"`);
setUserEmail(user.email);
});
}
useEffect(() => {
userInfo();
}, []);
return (
<div>
<h3>Hi, {userEmail}</h3>
<button onClick={logout}>Logout...</button>
<h4>Your reviews:</h4>
<hr />
<div className="Hotels">
{hotels.map((hotel, id) => (
<Hotel key={id} {...hotel} filter={true} user={userEmail} />
))}
</div>
</div>
);
}
export default MyAccount;
Hotels.jsx
import starsMap from "../../starsMap";
import { useEffect, useState } from "react";
import "./hotel.sass";
function Hotel(props, filter = false, user = null) {
const { name, img, localization, stars, review, author } = props;
const [userEmail, setUserEmail] = useState(user);
if (filter) {
console.log(author, userEmail);
if (author === user) {
return (
<div className="Hotel_card">
<h2 className="Hotel_card-name">{name}</h2>
<div className="Hotel_card_wrapper">
<img className="Hotel_card-img" src={img} alt="hotel_img" />
<h3 className="Hotel_card-localization">
{/* Lat:{localization._lat}
Long:{localization._lat} */}
<button>Show on map</button>
</h3>
{starsMap.get(stars)}
</div>
<p className="Hotel_card-review">{review}</p>
<h5 className="Hotel_card-author">Wroten by {author}</h5>
</div>
);
}
} else {
return (
<div className="Hotel_card">
<h2 className="Hotel_card-name">{name}</h2>
<div className="Hotel_card_wrapper">
<img className="Hotel_card-img" src={img} alt="hotel_img" />
<h3 className="Hotel_card-localization">
{/* Lat:{localization._lat}
Long:{localization._lat} */}
<button>Show on map</button>
</h3>
{starsMap.get(stars)}
</div>
<p className="Hotel_card-review">{review}</p>
<h5 className="Hotel_card-author">Wroten by {author}</h5>
</div>
);
}
}
export { Hotel };
The MyAccount.jsx component passes two attributes to the Hotels.jsx component - filter={true} user={userEmail}. Hotels.jsx only sees filter={true}, user remains null for it. Question - why doesn't Hotels.jsx see the user={userEmail} passed to it?
If you look at the state userEmail in MyAccount.jsx, then the desired value is found this way, but it is lost at the moment it is transferred to Hotels.jsx
CodePudding user response:
It's because you are using an intermediate useState
in the Hotel.jsx
file and you are not receiving correctly the props
const [userEmail, setUserEmail] = useState(user);
remove that line (it seems that you are not using it anyway) and change in the Hotels.jsx
component the prop user
to userEmail
:
function Hotel({filter = false, userEmail = null, ...props})
CodePudding user response:
A React Functional Component, is a function
that returns some JSX code. When you write it like:
<Hotel key={id} {...hotel} filter={true} user={userEmail} />
This is JSX, and this code gets converted to React first class API:
React.createElement(
Hotel,
[props],
[...children]
)
props
are filter
, user
and whatever comes out of {...hotel}
.
The React.createElement
just takes props
and children
( if at all ), and passes an object to your Hotel
function with them all inside, remember that props
is an object:
Hotel(props)
Being an object, when you want to recall your props from within your Component, you have two possible ways:
function Hotel (props) {
console.log(props.filter, props.user)
}
or through destructuring them directly when declaring them:
function Hotel ({filter, user}) {
console.log(filter, user)
}
If you are passing other props that you don't want to name directly:
function Hotel ({filter, user, ...props}) {
console.log(filter, user, props)
}