Posting State to firebase - javascript

I am trying to post name from state to firebase, and keep getting status 405.
I have tried changing how i import and send the data, but I cannot figure out where I am going wrong.
Index.js:
import React, { Component, Fragment, useState } from "react";
import { render } from "react-dom";
import axios from "axios";
import firebase from "firebase";
import { firebaseConfig } from "./firebase";
import Header from "./components/Header";
import "./style.css";
const App = () => {
const [name, setName] = useState("Ryan");
const handleClick = e => {
console.log("Working");
axios.post(
"https://lq-time-tracking.firebaseio.com/",
{ name },
{ firebaseConfig }
);
};
return (
<div>
<Header name={name} handleClick={handleClick} setName={setName} />
</div>
);
};
render(<App />, document.getElementById("root"));
Header.js:
import React from "react";
import styled from "styled-components";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Home from "./Home";
import "../style.css";
const Header = ({ name, handleClick, setName }) => {
return (
<Router>
<nav className="navbar">
<Link className="nav-item" to="/contact">
Contact
</Link>
<Link className="nav-item" to="/about">
About
</Link>
<Link className="nav-item" to="/home">
Home
</Link>
</nav>
<Switch>
<Route
exact
path="/home"
render={(...props) => (
<Home name={name} handleClick={handleClick} setName={setName} />
)}
/>
</Switch>
</Router>
);
};
export default Header;
Home.js:
import React, { Fragment } from "react";
const Home = ({ name, setName, handleClick }) => {
return (
<>
<h1>This is my State: {name}</h1>
<input type="text" onChange={e => setName(e.target.value)} />
<button type="Submit" onClick={e => handleClick(e)}>
Submit
</button>
</>
);
};
export default Home;

If I am not mistaking, since you use https://lq-time-tracking.firebaseio.com (which is a Firebase Realtime Database URL) I understand that you are trying to write the value name to the Realtime Database by performing a POST request to the https://lq-time-tracking.firebaseio.com URL.
This will not work because, as explained in the doc, while you can use the Firebase Realtime Database URL as a REST endpoint, you "need to append .json to the end of the URL".
In addition, in your case, I think you should use a PUT since you just want to write a string to your Firebase database.
It is not clear in your question, where you want to write the data in the database, but if you want to write the value name to the name subnode of the users/user1 node, you would do as follows:
axios.put("https://lq-time-tracking.firebaseio.com/users/user1.json", {name})

Related

How to run a function with default "id" on start using useEffect hook in react?

I am making a simple blog post site where user can post an entry.
The objective is:
To have the Homepage display all the blog post in a list and details of any one blog post next to it when the Homepage first loads. When the user clicks on any item from the list the details of which will replace the default blog details.
Basically how Indeed displays the job posts.
Method:
I make 2 Axios calls one to get all the data and the other to get data by id.
The data from getAllData is displayed in a list on HomePage The data is passed as props to HomePageListItems which are wrapped in <Link to= {/${idx}}/>
I use the useParams to get the id and make getDataId call in DataById.
So, HomePage has to child components HomePageListItems and DataById
Issue is:
Function getDataById in does not work when Homepage is first loaded. It only works when route is "localhost/:id" which is "localhost:3000/ae86140b-7ae6-457-826c-5bd324b8cb3"
Because I want one blog already displayed when the first loads: How I do have this getDatabyId function run with a preset id where the id changes when the user clicks on a list item?
The code is:
import React, { useState, useEffect, usePrevious } from "react";
import { Link, useParams } from "react-router-dom";
import Axios from "axios";
import HomePageListItems from "./homePageListItems";
import DataById from "./dataById";
export default function HomePage(props){
<DataById/>
const [getAllData, setGetAllData] = useState()
const getData =async () => {
await Axios.get("http://localhost:5000/get").then((response)=>{
setGetAllData(response.data)
})
.catch((error)=>{console.log(error)})
}
useEffect(()=>{
getData();
},[])
return(
<section>
<Link to = "/postJournal">Post Journal Entry</Link>
{getAllData&&getAllData.map((item)=>{
return(
<HomePageListItems
key={item.id}
idx={item.id}
name={item.name}
title={item.title}
journalEntry={item.journalEntry}
date={item.date}
file={item.file}
/>
)
})
}
{usePrevious}
<DataById/>
</section>
)
}
--
import React, { useState, useEffect, usePrevious } from "react";
import { useParams } from "react-router-dom";
import Axios from "axios";
export default function DataById(props){
console.log("DataProps",props)
const [axiosGetData, setAxiosGetData] = useState([])
const {id} = useParams()
const getDataById =async () => {
await Axios.get(`http://localhost:5000/${id}`).then((response)=>{
setAxiosGetData(response.data[0])
console.log("Data",response.data[0])
})
.catch((error)=>{console.log(error)})
}
useEffect(()=>{
getDataById("35b48be0-0ab8-4409-a5eb-a0c4dbd0a4b3");
},[id])
return(
<>
<p> DataByID</p>
name:{axiosGetData.name}
Date:{axiosGetData.date}
Journal:{axiosGetData.journalEntry}
{usePrevious}
</>
)
}
--
import React, { useState, useEffect, usePrevious} from "react";
import { Link} from "react-router-dom";
export default function HomePageListItems(props){
let {name,title,journalEntry,date,file,idx}=props
return(
<main className= "homepage">
<Link to={`/${idx}`} >
<section className="homepage__listContainer">
<ul className = "homepage__list">
<li className="homepage__listItemWrapper">
<div className ="homepage__listItem">
<div className = "homepage__listItemImgWrapper">
<img className = "homepage__listItemImg" alt="" src={file}/>
</div>
<h3 className= "homepage__listItemTitle">Title:{title}</h3>
<p className = "homepage__listItemAuthor">Name:{name}</p>
<p className = "homepage__listItemDescription">Description:{journalEntry}</p>
<p className = "homepage__listItemDate">Posted Date:{date}</p>
<p>Key:{idx}</p>
</div>
</li>
</ul>
</section>
</Link>
{usePrevious}
</main>
)
}
--
import React from "react";
import "./style/App.css";
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Router, Route } from "react-router-dom";
import HomePage from "./components/homePage"
import PostJournalEntry from "./components/postJournalEntry"
import DataByIDfrom "./components/dataById"
function App() {
return (
<div className="app">
<BrowserRouter>
<Switch>
<Route path="/:id" exact component = {HomePage}/>
<Route path="/:id" exact component = {DataByID}/>
<Route path="/postJournal" exact component = {PostJournalEntry}></Route>
<Route path="/" exact component = {HomePage}/>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
Thanks in advance guys! Any help is appriciated.
It's because getDataById doesn't accept any arguments, it always uses the URL id (useParams) for the axios get call, passing it an id in the useEffect won't do anything. You need to add a parameter to the function and then add some logic so it knows whether to use a passed in value or the URL id value. You could try something like this:
const getDataById = async (startupId = null) => {
await Axios.get(`http://localhost:5000/${startupId ? startupId : id}`).then((response)=>{
setAxiosGetData(response.data[0])
console.log("Data",response.data[0])
})
.catch((error)=>{console.log(error)})
}
This way if you pass getDataById an argument it will use that value for the axios call, otherwise it will try to use the id value from useParams

How can I make an api call dynamic with react?

How can I use the value from the input form and only make an api call when the button is submitted?
Right now when I press submit I am receiving back the user name which is what I expect and want to receive, however it doesn't seem to be sending the information back to userCard. I realize right now I'm not calling it in the form but I'm a bit unsure how to approach this one.
import React,{useEffect, useState} from "react";
import {Form, Button} from "react-bootstrap"
import axios from "axios";
import UserCard from "./Card";
const UserForm = () => {
const[user, setUser] = useState("");
const[login, setLogin] = useState("");
const handleChange = (e) =>{
//console.log(e.target.value)
setUser(e.target.value);
}
const handleSubmit = (e) =>{
//e.preventDefault();
console.log("Button was submitted",user);
axios.get(`https://api.github.com/users/${user}`)
.then((res =>
{setLogin(res.data);
})
)
.catch(err => console.log(err));
}
return (
<div className = "Form">
<Form onSubmit={handleSubmit} onChange = {handleChange} spellcheck="false" >
<Form.Group controlId="formName">
<Form.Label> Github Handle </Form.Label>
<Form.Control type="text" placeholder="Enter Handle Here" />
</Form.Group>
<Button onClick = {handleSubmit}>Submit</Button>
</Form>
</div>
)
}
export default UserForm;
import React from "react"
import { NavLink } from "react-router-dom"
import UserForm from "./UserForm"
const UserCard = (props) =>{
return(
<div className = "Card">
<UserForm />
<h1>Hello, {props.login}</h1>
<h2>How is the weather in {props.location}?</h2>
<h3>Here's a little about you </h3>
<p>{props.bio}</p>
<nav>
<ul className = "cardlist">
<li><NavLink to = "/followers" style={{ textDecoration: 'none' }}>Go To Followers</NavLink></li>
<li><NavLink to = "/repos" style={{ textDecoration: 'none' }}>Go To Repos</NavLink> </li>
</ul>
</nav>
</div>
)
}
export default UserCard;
import './App.css';
import React from "react";
import axios from "axios";
import { BrowserRouter, Link, Route } from 'react-router-dom';
import UserCard from "./components/Card";
import Followers from "./components/Followers";
import Repos from "./components/Repos";
import UserForm from "./components/UserForm"
let followerArray = [];
class App extends React.Component {
state = {
user: '' ,
location : '',
bio: '',
followers: [],
repos: []
}
//make api calls after the component mounts --> equivalent to useEffect()
//componentDidUpdate is equivalent to useEffect(,[])
componentDidMount() {
console.log("Component mounted");
//get user data
console.log("finished")
//get repos
}
render()
{
return (
<BrowserRouter>
<div className="App">
<Route exact path = "/">
<UserCard name = {this.state.name}
login = {this.state.user}
location = {this.state.location}
bio = {this.state.bio}
/>
</Route>
<Route path = "/followers" followers ={this.state.followers}>
<Followers />
</Route>
<Route path = "/repos">
<Repos repos={this.state.repos}/>
</Route>
</div>
</BrowserRouter>
);
}
}
export default App;
When you want to get back some values from child component, you can pass a function to child component. In your case:
Define a Callback function in UserCard component and use the callback function data in card:
import React from "react"
import { NavLink } from "react-router-dom"
import UserForm from "./UserForm"
const UserCard = (props) =>{
const[user, setUser] = useState("");
const[login, setLogin] = useState("");
const giveBackDataToCard = (login , user) => {
setLogin(login);
setUser(user);
}
return(
<div className = "Card">
<UserForm />
<h1>Hello, {login}</h1>
<h2>How is the weather in {user.location}?</h2>
<h3>Here's a little about you </h3>
<p>{user.bio}</p>
<nav>
<ul className = "cardlist">
<li><NavLink to = "/followers" style={{ textDecoration: 'none' }}>Go To Followers</NavLink></li>
<li><NavLink to = "/repos" style={{ textDecoration: 'none' }}>Go To Repos</NavLink> </li>
</ul>
</nav>
</div>
)
}
export default UserCard;
Call props function where you want:
import React,{useEffect, useState} from "react";
import {Form, Button} from "react-bootstrap"
import axios from "axios";
import UserCard from "./Card";
const UserForm = () => {
const handleChange = (e) =>{
setUser(e.target.value);
}
const handleSubmit = (e) =>{
e.preventDefault();
axios.get(`https://api.github.com/users/${user}`)
.then((res =>
{
setLogin(res.data);
//------------> For example here
props.giveBackDataToCard(res.data,e.target.value);
})
)
.catch(err => console.log(err));
}
return (
<div className = "Form">
<Form onSubmit={handleSubmit} onChange={handleChange} spellcheck="false" >
<Form.Group controlId="formName">
<Form.Label> Github Handle </Form.Label>
<Form.Control type="text" placeholder="Enter Handle Here" />
</Form.Group>
<Button onClick = {handleSubmit}>Submit</Button>
</Form>
</div>
)
}
export default UserForm;
Well, If your question is if you want send back the data to the userCard from userForm, You should follow these methods.
First method is, You should learn first a Context APIs in react which already mentioned in docs https://reactjs.org/docs/context.html , use it for passing data between a screen.
Second method is, Always call the API at parent level component, I think its a better and easier way. By calling API from parent level component you will have to pass some props to according to your useForm required.
Third method is, The best way to use some state management store, like Mobx, Redux etc... It is a best way. You can then actually pass your state dynamically to your useCard component.
If answer matched you question, that will great, If not tell so that I will delete for community help.

How to understand a React file

I am using React in Laravel and I found a problem that I can't refresh or reload a page in React. So to solve this problem I found many suggestions like use historyApiFallback, 404 page and many other ways But I found none of them useful to me now.
I know I can't do this because React has no system for it because of server- and client-side routing. Then i found a demo project where they used Redux and I can refresh their page. I got the demo project where i can use any component and refresh them how many times I want. So there is a file name with Base.js and I am not understanding this file why he used it what is doing. Let me share the file and where it was used.
Base.js
import React from 'react';
import { connect } from 'react-redux';
import Header from './components/Header';
const Base = ({ children }) => (
<div>
<Header />
<main>{children}</main>
</div>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Base);
Header.Js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {
Nav,
NavItem,
NavLink,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from 'reactstrap';
import * as actions from '../store/actions';
class Header extends Component {
handleLogout = (e) => {
e.preventDefault();
this.props.dispatch(actions.authLogout());
};
render() {
return (
<header className="d-flex align-items-center justify-content-between">
<h1 className="logo my-0 font-weight-normal h4">
<Link to="/">Laravel React</Link>
</h1>
{this.props.isAuthenticated && (
<div className="navigation d-flex justify-content-end">
<Nav>
<NavItem>
<NavLink tag={Link} to="/archive">
Archive
</NavLink>
<NavLink tag={Link} to="/Myfile">
Myfile
</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
Account
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>Settings</DropdownItem>
<DropdownItem divider />
<DropdownItem onClick={this.handleLogout}>
Log Out
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</div>
)}
</header>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Header);
Public.js
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import Base from '../Base';
const PublicRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) => (
<Base>
<Component {...props} />
</Base>
)}
/>
);
PublicRoute.propTypes = {};
export default PublicRoute;
split.js
import React from 'react';
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import { connect } from 'react-redux';
import Base from '../Base';
const SplitRoute = ({
component: Component,
fallback: Fallback,
isAuthenticated,
...rest
}) => (
<Route
{...rest}
render={(props) => (isAuthenticated ? (
<Base>
<Component {...props} />
</Base>
) : (
<Base>
< Fallback {...props} />
</Base>
))}
/>
);
SplitRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
};
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(SplitRoute);
Now it has authenticated system so I understand it but why it is using base function and what it is doing? I am not understanding.
What it looks like is that the Base.js is a container for the Header and any rendered children (passed props). This is a good practise in react to separate logic and make it more readable. So when he imports Base into the Public.js file, it will render the Header and the component he is passing to it from the public function props.
Think of it like the skeleton of the layout, by importing Base it will always render the header and any logic inside of the header file, and whatever he is passing down to it. As you can see he is passing different components to it depending on whether isAuthenticated is true or false. If it is false, they are rendering Base and passing a fallback component - this will render inside of the main tag within the Base function.

React router - url changes, no render

Using a simple link to / route to via React browser Router.
I got it to work fine with routing to the root component (/), however it does not function as expected when trying to route to (/drink/:drinkId), though the URL changes and the page loads if I manually try to access it.
App component:
import React from "react";
import "./App.css";
import Cocktails from "./Cocktails";
import { Container } from "react-bootstrap";
import NavApp from "./Navbar";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import DrinkDetails from "./DrinkDetails";
import "./App.css";
function App() {
return (
<Router>
<Container className="App-container">
<NavApp />
<Switch>
<Route exact path="/">
<Cocktails size={20} />
</Route>
<Route exact path="/drink/:drinkId">
<DrinkDetails />
</Route>
</Switch>
</Container>
</Router>
);
}
export default App;
Drink details component:
import { React, useState, useEffect } from "react";
import { Jumbotron, Button } from "react-bootstrap";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
} from "react-router-dom";
import axios from "axios";
function DrinkDetails() {
let { drinkId } = useParams();
const [drink, setDrink] = useState(null);
const [ingrdts, setIngrdts] = useState([]);
useEffect(() => {
const getDrinkSpecs = async () => {
const res = await axios.get(
`https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${drinkId}`
);
let newDrink = res.data.drinks[0];
setDrink(newDrink);
let newIngrdts = [];
for (let i = 1; i <= 15; i++) {
if (newDrink[`strIngredient${i}`] != null) {
let ingrdtVal = {};
ingrdtVal["ing"] = newDrink[`strIngredient${i}`];
ingrdtVal["val"] = newDrink[`strMeasure${i}`];
newIngrdts.push(ingrdtVal);
}
}
setIngrdts([...newIngrdts]);
};
getDrinkSpecs();
}, [drinkId]);
return drink ? (
<Jumbotron>
<h1>
{drink.strDrink}
<img src={drink.strDrinkThumb} />
</h1>
<p>Glass: {drink.strGlass}</p>
<p>Category: {drink.strCategory}</p>
<p>Instructions: {drink.strInstructions}</p>
{ingrdts.map((ingrdt) => (
<p>
{ingrdt.ing} : {ingrdt.val}
</p>
))}
<p>
<Button variant="primary">Learn more</Button>
</p>
</Jumbotron>
) : (
<Jumbotron>
<h1>Hmmm... we don't have this yet!</h1>
<p>
This is a simple hero unit, a simple jumbotron-style component for
calling extra attention to featured content or information.
</p>
<p>
<Button variant="primary">Learn more</Button>
</p>
</Jumbotron>
);
}
export default DrinkDetails;
and this is where I use Link:
import React from "react";
import { Button, Card } from "react-bootstrap";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import "./Card.css";
function CardDrink({ data, select }) {
return (
<Router>
<Card className="Cocktail-card">
<Link to={`/drink/${data.idDrink}`}>
<Card.Img
variant="top"
src={data.strDrinkThumb}
className="Cocktail-card-img"
onClick={() => select(data.idDrink)}
/>
</Link>
<Card.Body>
<Card.Title>{data.strDrink}</Card.Title>
</Card.Body>
</Card>
</Router>
);
}
export default CardDrink;
Remove <Router> from CardDrink component. You need only one Router at root level which you already have in App component.
Also, as a practice don't keep unused imports in your component. I see Router imported in DrinkDetails component as well.
From docs
To use a router, just make sure it is rendered at the root of your element hierarchy. Typically you’ll wrap your top-level element in a router.
Try to use the useHistory() hook:
import React from "react";
import { Button, Card } from "react-bootstrap";
import { BrowserRouter as Router, Switch, Route, Link, useHistory } from "react-router-dom";
import "./Card.css";
function CardDrink({ data, select }) {
const history = useHistory()
return (
<Router>
<Card className="Cocktail-card">
<div onClick={()=>history.push(`/drink/${data.idDrink}`)}>
<Card.Img
variant="top"
src={data.strDrinkThumb}
className="Cocktail-card-img"
onClick={() => select(data.idDrink)}
/>
</div>
<Card.Body>
<Card.Title>{data.strDrink}</Card.Title>
</Card.Body>
</Card>
</Router>
);
}
export default CardDrink;

Is there a way to stop my header from re-rendering when navigating my site?

I'm creating a website using React JS, React-Router-Dom, React-Redux & React-Persist.
I set up a login & sign up page with firebase. When a user logs in or signs up, I would like to have their display name in the header-component. Using my current method, I realized that when a user is logged in, the header component re-renders every time, however, I'm not too fond of that since it doesn't make navigating my website smooth. When the user is not logged in, the header component doesn't re-render.
I'm relatively new to React JS and was reading the documentation & googling other similar problems, but I can not find a solution and having a hard time approaching this. Any assistance or suggestions would be greatly appreciated!
Below are my index.js, App.js, header.component.jsx
index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import "bootstrap/dist/css/bootstrap.css";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { store, persistor } from "./redux/store";
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
App.js
import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import "./App.css";
import Header from "./components/header/header.component";
import Footer from "./components/footer/footer.component";
import HomePage from "./pages/homepage/homepage.page";
import SponsorsPage from "./pages/sponsors/sponsors.page";
import TeamPage from "./pages/team/team.page";
import AccountPage from "./pages/myaccount/myaccount.page"
import SignInAndSignUpPage from "./pages/sign-in-and-sign-up/sign-in-and-sign-up.page";
import { auth, createUserProfileDocument } from "./firebase/firebase.util";
import { setCurrentUser } from "./redux/user/user.action";
import { createStructuredSelector } from "reselect";
import { selectCurrentUser } from "./redux/user/user.selector";
class App extends React.Component {
unSubscribeFromAuth = null;
componentDidMount() {
const { setCurrentUser } = this.props;
this.unSubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot((snapShot) => {
setCurrentUser({
id: snapShot.id,
...snapShot.data(),
});
});
}
setCurrentUser(userAuth);
});
}
componentWillUnmount() {
this.unSubscribeFromAuth();
}
render() {
return (
<div>
<Header />
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/sponsors" component={SponsorsPage} />
<Route exact path="/team" component={TeamPage} />
<Route exact path="/myaccount" component={AccountPage} />
<Route
exact
path="/signin"
render={() =>
this.props.currentUser ? <Redirect to="/" /> : <SignInAndSignUpPage/>
}
/>
</Switch>
<Footer />
</div>
);
}
}
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
setCurrentUser: (user) => dispatch(setCurrentUser(user)),
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
header.component.jsx
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectCurrentUser } from "../../redux/user/user.selector";
import { auth } from "../../firebase/firebase.util";
import { ReactComponent as Logo } from "../../assets/eaglerocketry-icon.svg";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import "./header.style.scss";
const Header = ({ currentUser }) => (
<Navbar collapseOnSelect expand="md" bg="light" fixed="top">
<Navbar.Brand className="mr-auto">
<Logo className="logo" />
</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="pl-md-4">
<Nav.Link href="/">HOME</Nav.Link>
<Nav.Link href="/outreach">OUTREACH</Nav.Link>
<Nav.Link href="/team">TEAM</Nav.Link>
<Nav.Link href="/sponsors">SPONSORS</Nav.Link>
</Nav>
<Nav className="ml-auto">
{currentUser ? <Nav.Link href="/myaccount">{currentUser.displayName}</Nav.Link> : null}
{currentUser ? (
<Nav.Link onClick={() => auth.signOut()}>SIGN OUT</Nav.Link>
) : (
<Nav.Link href="/signin">SIGN IN</Nav.Link>
)}
</Nav>
</Navbar.Collapse>
</Navbar>
);
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
});
export default connect(mapStateToProps)(Header);
Every time that a prop (in this case currentUser) changes in a stateless component (like your Header component) is gonna re-render, because you are using that prop inside or your component, not only for displaying the displayName, but also to conditionally render some links ( <Nav.Link> ). So it is inevitable that a react component doesn't re-render if its props change.
being relatively new React JS I found a solution to my question.
I had to make my functional component into a class and have a local state that stores the name & use that in my render() function instead of this.props.currentUser.displayName.
class Header extends React.Component {
constructor(props){
super(props);
this.state = {
name: this.props.currentUser.displayName,
};
}

Categories