Unexpected React error when passing state down - node.js

Right now, I have this code (showing generic):
import {useState} from 'react';
const parentComponent = () => {
const [show, setShow] = useState(false);
return
(<>
<childComponent setShowDependent={() => setShow(true)} />
{ show && <dependentComponent /> }
</>);
}
const childComponent = ({setShowDependent}) => {
return <Button onClick={setShowDependent} />;
}
and I am getting the warning in react dev tools:
Warning: Cannot update a component (`parentComponent`) while rendering a different component (`childComponent`).
and it is not working properly. What am I doing wrong?

React component name must start with an uppercase letter
import {useState} from 'react';
const ParentComponent = () => {
const [show, setShow] = useState(false);
return (<>
<ChildComponent setShowDependent={() => setShow(true)} />
{ show && <DependentComponent /> }
</>);
}
const ChildComponent = ({setShowDependent}) => {
return <Button onClick={setShowDependent} />;
}

Related

Not able render the images using an API

I am using multi avatar api to render random images on the UI, but I am getting the below-mentioned error. I also tried using promises to render the UI but failed to get the results.
Uncaught TypeError: The first argument must be one of type string,
Buffer, ArrayBuffer, Array, or Array-like Object. Received type
undefined
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import axios from "axios";
import { profilePicRoute } from "../utils/apiRoutes";
import { Buffer } from "buffer";
function ProfilePic() {
const api = "https://api.multiavatar.com";
const navigate = useNavigate();
const [profilePic, setProfilePic] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedPofilePic, setSelectedPofilePic] = useState(undefined);
const toastStyles = {
position: "top-center",
};
const setProfilePicture = async () => {};
useEffect(() => {
const data = [];
for (let i = 0; i < 4; i++) {
const image = axios.get(`${api}/${Math.round(Math.random() * 1000)}`);
const buffer = Buffer(image.data);
data.push(buffer.toString("base64"));
console.log(data);
}
setProfilePic(data);
setIsLoading(false);
}, []);
return (
<div className="profilePage">
<h1>Pick your favorite profile picture</h1>
<div className="profilePics">
{profilePic.map((pic, index) => {
return (
<div
key={index}
className={`pic ${selectedPofilePic === index ? "selected" : ""}`}
>
<img
src={`data:image/svg+xml;base64,${pic}`}
alt="profile pic"
onClick={() => setSelectedPofilePic(index)}
/>
</div>
);
})}
</div>
<ToastContainer />
</div>
);
}
export default ProfilePic;
Since you were using the async you must have to use await keyword , otherwise it will return promises,and you should use the function inside the useEffect
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import axios from "axios";
import { profilePicRoute } from "../utils/apiRoutes";
import { Buffer } from "buffer";
function ProfilePic() {
const api = "https://api.multiavatar.com";
const navigate = useNavigate();
const [profilePic, setProfilePic] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedPofilePic, setSelectedPofilePic] = useState(undefined);
const toastStyles = {
position: "top-center"
};
useEffect(() => {
const setProfilePicture = async () => {
const data = [];
for (let i = 0; i < 4; i++) {
const image = await axios.get(
`${api}/${Math.round(Math.random() * 1000)}`
);
console.log(image);
const buffer = Buffer(image.data);
data.push(buffer.toString("base64"));
}
setProfilePic(data);
setIsLoading(false);
};
setProfilePicture();
}, []);
return (
<div className="profilePage">
<h1>Pick your favorite profile picture</h1>
<div className="profilePics">
{profilePic.map((pic, index) => {
return (
<div
key={index}
className={`pic ${selectedPofilePic === index ? "selected" : ""}`}
>
<img
src={`data:image/svg+xml;base64,${pic}`}
alt="profile pic"
onClick={() => setSelectedPofilePic(index)}
/>
</div>
);
})}
</div>
<ToastContainer />
</div>
);
}
export default ProfilePic;
Hope this code will help you.
Happy Coding :)

Authentication reactjs website with Firebase using email and password

I tried to create an authentication website with Firebase using email and password. I can't even load the Login page.
Here's Auth.js
import React, { useState, useEffect} from "react";
import { auth } from './config'
import { onAuthStateChanged } from "firebase/auth";
export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
setCurrentUser(user);
})
}, [])
return (
<AuthContext.Provider value={{currentUser}}>
{children}
</AuthContext.Provider>
)
}
And this is Login.js
import React, {useContext ,useState } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import "./Login.css";
import { auth } from './config'
import { signInWithEmailAndPassword } from "firebase/auth";
import { AuthContext } from "./Auth";
import { useHistory } from "react-router-dom";
const Login = () => {
let history = useHistory();
const handleSubmit = (event) => {
event.preventDefault();
const { email, password } = event.target.elements;
signInWithEmailAndPassword(auth, email.value, password.value)
.then((userCredential) => {
const user = userCredential.user;
console.log(user.uid);
})
.catch((error) => {
console.log(error.massage);
});
}
const currentUser = useContext(AuthContext);
if(currentUser) {
return history.push('/dashboard');
}
return (
<div className="Login">
<h1>Login</h1>
<Form onSubmit={handleSubmit}>
//Login Form
</Form>
</div>
);
}
export default Login
And DashBoard.js
import React, {useContext} from 'react'
import { AuthContext } from './Auth'
import { auth } from './config'
import { signOut } from 'firebase/auth'
import { useHistory } from "react-router-dom";
const DashBoard = () => {
const currentUser = useContext(AuthContext);
let history = useHistory();
if(!currentUser) {
return history.push('/login');
}
const signOutFunc = () => {
signOut(auth)
}
return (
<div>
<div className='container mt-5'>
<h1>Welcome</h1>
<h2>If you see this you are logged in.</h2>
<button className='btn btn-danger' onClick={signOutFunc}>Sign Out</button>
</div>
</div>
)
}
export default DashBoard;
Lastly App.js
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom'
import Login from './Login'
import DashBoard from './DashBoard';
import { AuthProvider } from './Auth'
function App() {
return (
<AuthProvider>
<Router>
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/dashboard" component={Dashboard} />
</Switch>
</Router>
</AuthProvider>
);
}
export default App;
When I open /login, it would send me to /dasgboard immediately. If I typed /login again it gives me this error
Error: Login(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
I can't figure it out what's wrong with it. Please help me.
Thank you
You have multiple places in your code where you return history.push('/dashboard'); or another path. You should return there a null:
if(!currentUser) {
history.push('/login');
return null
}

TypeError: _fire__WEBPACK_IMPORTED_MODULE_2__.default.auth is not a function

I've created a login page to my app using firebase authentication. then i've a contact/personal info form which takes images and files as input and uploads them to firebase storage. but i'm facing this issue. This is my first project using react and firebase - would appreciate some simple explanation.
here is my fire.js file
import firebase from 'firebase';
import "firebase/auth";
import "firebase/storage";
if (!firebase.apps.length) {
var fire,storage = firebase.initializeApp({
// my credentials //
});
}else {
fire = firebase.app();
storage = firebase.storage(); // if already initialized, use that one
}
//const fire = firebase.initializeApp(firebaseConfig);
export default {storage,fire};
and here is the page in which I'm trying to add a contact document and then add images to firebase storage:
import React, { useState } from "react";
import { render } from "react-dom";
import { storage } from "./firebase";
import fire from './fire';
const AddRecord = () => {
const [image, setImage] = useState(null);
const [url, setUrl] = useState("");
const [progress, setProgress] = useState(0);
const handleChange = e => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
snapshot => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(progress);
},
error => {
console.log(error);
},
() => {
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(url => {
setUrl(url);
});
}
);
};
console.log("image: ", image);
return (
<div>
<progress value={progress} max="100" />
<br />
<br />
<input type="file" onChange={handleChange} />
<button onClick={handleUpload}>Upload</button>
<br />
{url}
<br />
<img src={url || "http://via.placeholder.com/300"} alt="firebase-image" />
</div>
);
};
export default AddRecord;

React Hooks - How to pass props from child to parent component

In the bellow example, how can I pass imageAsUrl.imgUrl from the Child component (ImageUpload) to the parent component (UpdateCard).
CHILD Component
import React, { useState, useEffect } from 'react';
import { storage } from '../firebase';
const ImageUpload = () => {
const allInputs = { imgUrl: '' };
const [imageAsUrl, setImageAsUrl] = useState(allInputs);
const [image, setImage] = useState(null);
const handleChange = (e) => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
useEffect(() => {
if (image) {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
'state_changed',
(snapshot) => {},
(error) => {
console.log(error);
},
() => {
storage
.ref('images')
.child(image.name)
.getDownloadURL()
.then((fireBaseUrl) => {
setImageAsUrl((prevObject) => ({
...prevObject,
imgUrl: fireBaseUrl,
}));
});
}
);
}
}, [image]);
return (
<>
<label className='custom-file-upload'>
<input type='file' onChange={handleChange} />
</label>
<img src={imageAsUrl.imgUrl} alt='sample' />
</>
);
};
export default ImageUpload;
PARENT Component
import React, { useState } from 'react';
import firebase from '../firebase';
import ImageUpload from './ImageUpload';
const UpdateCard = ({ card }) => {
const [originalText, setOriginalText] = useState(card.originalText);
const [translatedText, setTranslatedText] = useState(card.translatedText);
const onUpdate = () => {
const db = firebase.firestore();
db.collection('FlashCards')
.doc(card.id)
.set({ ...card, originalText, translatedText });
timeOutScroll();
};
return (
<>
<div>
{card.imageURL ? (
<img src={card.imageURL} alt='' className='img' />
) : (
<textarea
className='upload-textarea'
value={originalText}
onChange={(e) => {
setOriginalText(e.target.value);
}}
/>
)}
<ImageUpload />
</div>
<textarea
value={translatedText}
onChange={(e) => {
setTranslatedText(e.target.value);
}}
/>
<button onClick={onUpdate}>Update</button>
</>
);
};
export default UpdateCard;
Inside parent,You can define a callback function as prop ref to be called inside the child.
const ImageUpload = ({getURLtoParent}) =>{ <--------------------
const [imageAsUrl, setImageAsUrl] = useState(allInputs);
useEffect(() => {
uploadTask.on(
..............
...
);
if(imageAsUrl.imgUrl !== '')
getURLtoParent(imageAsUrl.imgUrl) <-----------------------
},[image])
}
const UpdateCart = () => {
const[imgURL,setimgURL] = useState(null)
return (
......
<ImageUpload getURLtoParent={ (url) => setimgURL(url) } /> <----------------
.........
)
}

Data Response Not able to map in the react router

I have created a e Commerce App in react. As you can see from the screenshot below, that when I click on the Apparels->Girls->Shoes , the data is not displayed in the screen.
So first, in the index.js file, I have set the BrowserRouter and created a component Main which holds all my other components.
index.js
import React from "react";
import ReactDOM from "react-dom";
import Main from "./Main";
import "./index.css";
import 'bootstrap/dist/css/bootstrap.css';
import {Route, NavLink, BrowserRouter} from 'react-router-dom';
ReactDOM.render((
<BrowserRouter>
<Main/>
</BrowserRouter>
)
,
document.getElementById("root")
);
After this I have created Main.js, where I have created components for Navigation and PLPMenu( which should display after clicking on the Girls->Shoes). Also in the Main.js, I have set the switch and Route paths
Main.js
import React, { Component } from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
import { Route, Switch } from 'react-router-dom';
import Navigation from "./components/topNavigation";
import Footer from "./components/Footer";
import Banner from "./components/Banner";
import PLPMenu from "./components/PLPMenu";
import PDP from "./components/PDP";
import Home from "./components/Home";
class Main extends Component {
render() {
return (
<div>
<Navigation />
<Switch>
<Route exact path="/" component={Home} />
<Route path="Apparel/Girls/:id" component={PLPMenu}/>
<Route path="/PDP" component={PDP} />
<Route path="/Banner" component={Banner} />
<Route path="/Footer" component={Footer} />
</Switch>
</div>
)
}
}
export default Main;
In the topNavigation.js, I'm displaying the first level of categories like Apparel, Electronics, Grocery etc. Also, I have created, a component SubMenu for displaying the second level of categories like Girls, Boys, Women etc.
topNavigation.js
import React, { Component } from 'react';
import axios from 'axios';
import SubMenu from './subMenu';
class Navigation extends Component {
state = {
mainCategory: []
}
componentDidMount() {
axios.get('http://localhost:3030/topCategory')
.then(res => {
console.log(res.data.express);
this.setState({
mainCategory: res.data.express.catalogGroupView
})
})
}
render() {
const { mainCategory } = this.state;
return mainCategory.map(navList => {
return (
<ul className="header">
<li key={navList.uniqueID}>
<a className="dropbtn ">{navList.name} </a>
<ul className="dropdown-content">
<SubMenu below={navList.catalogGroupView} />
</ul>
</li>
</ul>
)
})
}
}
export default Navigation;
subMenu.js
In the submenu.js, I have created one more component SubListMenu for displaying the inner categories like Shoes, Pants, Skirts, Tops etc.
import React, { Component } from 'react';
import SubListMenu from './subListMenu';
class SubMenu extends Component {
render() {
const { below } = this.props;
return below.map(sub => {
return (
<React.Fragment>
<li key={sub.uniqueID}>
<a>{sub.name}</a>
{
<ul className="sub-menu">
{sub.catalogGroupView !== undefined && <SubListMenu id={sub.uniqueID} subBelow={sub.catalogGroupView} />}
</ul>
}
</li>
</React.Fragment>
)
})
}
}
export default SubMenu;
subListMenu.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
class SubListMenu extends Component {
render() {
const { subBelow, id } = this.props;
console.log(subBelow)
return(
<React.Fragment>
{subBelow && subBelow.map(subl => {
return (
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${subl.name}/${ subl.uniqueID }`}>{subl.name}</Link></li>
)
})
}
</React.Fragment>
)
}
}
export default SubListMenu;
As you can see from my subListMenu.js code, that I have set the Link to PLPMenu.js. But in my case it's not happening. Also, the part Apparel/Girls in the Link, I have hard coded which i'm not able to make it dynamic.
PLPMenu.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
class PLPMenu extends Component {
state = {
shoeCategory: []
}
componentDidMount() {
let pathname= this.props.match.params.id
console.log(pathname)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => (res.json()))
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
render() {
const { shoeCategory } = this.state;
const picUrl = 'https://149.129.128.3:8443'
return (
<div>
<div className="container">
<div className="row">
{
shoeCategory && shoeCategory.map(shoeList => (
<div className="col-md-4">
<h2 key={shoeList.uniqueID}></h2>
<img src={picUrl + shoeList.thumbnail} />
<Link to="/PDP"><p className="pdp">{shoeList.name}</p></Link>
<p>Price : {shoeList.price[0].value} {shoeList.price[0].currency}</p>
</div>
))
}
</div>
</div>
</div>
)
}
}
export default PLPMenu;
For fetching the data, I have used a node server.
server.js
const express = require('express');
const cors = require('cors');
const Client = require('node-rest-client').Client;//import it here
const app = express();
app.use(cors());
app.get('/topCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/categoryview/#top?depthAndLimit=-1,-1,-1,-1", (data, response) => {
res.send({ express: data });
});
});
app.get('/GirlShoeCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/productview/byCategory/10015", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port${port}`));
I don't know where my code is getting wrong. Maybe I feel that from the node server, there is a mismatch with the reactjs routes, for which only in the url, it's displaying the link but not the contents. Can someone please give me an insight on this. My console browser window:
for this issue
In the PLPMenu.js page, I'm trying to fetch the data. But all I'm getting is this undefined.
componentDidMount() {
let pathname= this.props.match.params.id
console.log(this.props.match.params.id)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => {return res.json();})
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
try this it will solve undefined issue.
I believe you have to take id from subBelow instead this.props.id.
so change the code like this.
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${ subl.uniqueID }`}>{subl.name}</Link></li>
The reason you get undefined in URL bar because you are not passing the unique id from SubMenu down to SubListMenu component.
What you need to do is
SubMenu.js
import React, { Component } from 'react';
import SubListMenu from './subListMenu';
class SubMenu extends Component {
render() {
const { below } = this.props;
return below.map(sub => {
return (
<React.Fragment>
<li key={sub.uniqueID}>
<a>{sub.name}</a>
{
<ul className="sub-menu">
{sub.catalogGroupView !== undefined && <SubListMenu id={sub.uniqueID} subBelow={sub.catalogGroupView} />}
</ul>
}
</li>
</React.Fragment>
)
})
}
}
export default SubMenu;
SubListMenus.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
class SubListMenu extends Component {
render() {
const { subBelow, id } = this.props;
console.log(subBelow)
return(
<React.Fragment>
{subBelow && subBelow.map(subl => {
return (
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${ id }`}>{subl.name}</Link></li>
)
})
}
</React.Fragment>
)
}
}
export default SubListMenu;
Regarding below issue You need to do res.json() and in next .then get the data
In the PLPMenu.js page, I'm trying to fetch the data. But all I'm getting is this undefined.
Do this
componentDidMount() {
let pathname= this.props.match.params.id
console.log(this.props.match.params.id)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => (res.json()))
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
Edit:
Add below condition in PLPMenu component
{shoeCategory && shoeCategory.map(shoeList => (

Resources