I have coded this so how to fetch the data as I have added social logins and phone so I have query where data gets stored in reactjs and how I have to fetch data I want e-mail and phone number and name when somebody login so that I can integrate apis
import React, { Component } from "react"
import firebase from "firebase"
import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth"
firebase.initializeApp({
apiKey: "AIzaSyBPqAebQzVeT5Kbd57TsDwoF_l3pRCVomY",
authDomain: "login-project-d33bf.firebaseapp.com"
})
class SocialLogin extends Component {
state = { isSignedIn: false }
uiConfig = {
signInFlow: "popup",
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
firebase.auth.FacebookAuthProvider.PROVIDER_ID,
firebase.auth.PhoneAuthProvider.PHONE_SIGN_IN_METHOD,
],
callbacks: {
signInSuccess: () => false
}
}
componentDidMount = () => {
firebase.auth().onAuthStateChanged(user => {
this.setState({ isSignedIn: !!user })
console.log("user", user)
firebase.database().ref("signInSuccess").on("value", snapshot => {
let signInSuccess = [];
snapshot.forEach(snap => {
signInSuccess.push(snap.val());
})
this.setState({signInSuccess : signInSuccess})
})
})
}
render() {
return (
<div className="App">
{this.state.isSignedIn ? (
<span>
<div>Signed In!</div>
<button onClick={() => firebase.auth().signOut()}>Sign out!</button>
<h1>Welcome {firebase.auth().currentUser.displayName}</h1>
<img
alt="profile picture"
src={firebase.auth().currentUser.photoURL}
/>
</span>
) : (
<StyledFirebaseAuth
uiConfig={this.uiConfig}
firebaseAuth={firebase.auth()}
/>
)}
{this.state.signInSuccess.map(data =>{
return (
<tr>
<td>{data.email}</td>
<td>{data.mobilenumber}</td>
</tr>
)
})}
</div>
)
}
}
export default SocialLogin
so where does the data get store because I have to fetch the data from the code so I have to fetch data useremail and phonenumber and name so how can I do it?
It looks like the error is occurring because this.state.signInSuccess is not an array. May be good to check if this.state.signInSuccess is an array with data prior to perform the .map
render() {
const { signInSuccess, isSignedIn } = this.state;
const isSignInSuccess = Array.isArray(signInSuccess);
return (
<div className="App">
{isSignedIn ? (
<span>
<div>Signed In!</div>
<button onClick={() => firebase.auth().signOut()}>Sign out!</button>
<h1>Welcome {firebase.auth().currentUser.displayName}</h1>
<img
alt="profile picture"
src={firebase.auth().currentUser.photoURL}
/>
</span>
) : (
<StyledFirebaseAuth
uiConfig={this.uiConfig}
firebaseAuth={firebase.auth()}
/>
)}
{isSignInSuccess && isSignInSuccess.map(data =>{
return (
<tr>
<td>{data.email}</td>
<td>{data.mobilenumber}</td>
</tr>
)
})}
</div>
)
}
Related
I've got a set of dashboards that display in bootstrap cards on a front page and I would like to wrap them in a div with the class row for every 3rd entry. I was thinking about marking my dashboard component with the DB id from props and use a modulus function, but that will cause problems if an ID is deleted
Dashboard component:
export type DashboardProps = {
id: number
title: string
description: string
}
const Dashboard: React.FC<{ dashboard: DashboardProps }> = ({ dashboard }) => {
return (
<>
<div className="col-sm-12 col-lg-4">
<div className="card bg-light h-100">
<div className="card-header">
{dashboard.title}
</div>
<div className="card-body d-flex flex-column">
<p className="card-text">
{dashboard.description}
</p>
<a className="btn btn-info text-center mt-auto"
onClick={() =>
Router.push("/dashboard/[id]", `/dashboard/${dashboard.id}`)
}
>Go to dashboard</a>
</div>
</div>
</div>
</>
)
}
export default Dashboard
Index page:
type Props = {
dashboards: DashboardProps[]
}
export const getServerSideProps: GetServerSideProps = async () => {
const dashboards = await prisma.dashboard.findMany({
orderBy: { id: "asc", },
})
return {
props: JSON.parse(JSON.stringify({ dashboards })),
}
}
const Index: React.FC<Props> = (props) => {
const { data: session, status } = useSession()
if (status === "loading") {
return (
<Spinner />
)
}
if (!session) {
return (
<Layout>
<AccessDenied />
</Layout>
)
}
return (
<Layout>
<h1>Dashboards</h1>
{props.dashboards.map((dashboard) => (
<Dashboard dashboard={dashboard} />
))}
</Layout>
)
}
export default Index
I could also potentially wrap them in a single div with class row, but I would need to enforce a top/bottom margin so the cards don't stack right on top of each other. Any tips to get me rolling on this would be greatly appreciated!
.map provides index, you this to find every 3rd element.
//...
{
props.dashboards.map((dashboard, index) =>
(index + 1) % 3 === 0 ? (
<div>
<Dashboard key={dashboard.id} dashboard={dashboard} />
</div>
) : (
<Dashboard key={dashboard.id} dashboard={dashboard} />
)
)
}
i have a reusable contact form that works perfectly when used in the index.js file.
However when i use it from a component in the page folder i am having a 404 not found error message because it uses this route 3000/ourServices/conciergerie/api/contact/ instead of 3000/api/contact.
How do i ensure the it will always fetch the correct route? please see how i fetch the api below :
async function handleSubmit() {
const data = {
firstName,
email,
phone,
message,
};
const res = await fetch("api/contact", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
data: data,
token: "test",
}),
});
alert("Message sent! Thank you\nWe will be in touch with you soon!");
}
pages/ourServices/conciergerie
import Image from "next/image";
import { AiOutlinePlus, AiOutlineMinus } from "react-icons/ai";
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import { Contact } from "../../components/contact/Contact";
import es from "../../locales/es-ES/conciergerie.json";
import en from "../../locales/en-US/conciergerie.json";
import Icon1 from "/public/1.svg";
import Icon2 from "/public/2.svg";
import Icon3 from "/public/3.svg";
const Conciergerie = () => {
let { locale } = useRouter();
let t = locale === "es-ES" ? es : en;
// const { t } = useTranslation(locale, "conciergerie");
let myIcons = [Icon1, Icon2, Icon3];
const scrollToConciergerie = () => {
window.scrollTo({
top: 300,
behavior: "smooth",
});
};
const myLoader = ({ src, width, quality }) => {
return `${src}?w=${width}&q=${quality || 75}`;
};
const [showform, setshowform] = useState(false);
useEffect(() => {
window.addEventListener("load", scrollToConciergerie);
return () => {
window.removeEventListener("load", scrollToConciergerie);
};
});
const showContactForm = () => {
return <Contact />;
};
const contentData = t.conciergerieData;
return (
<div className="section" onLoad={scrollToConciergerie}>
<div className="container">
<div className="text-center">
<h1 className=" my-4 text-capitalize" id="conciergerie">
{t.conciergerieHeader}
</h1>
</div>
<h3 className="text-capitalize concierge-subheading mt-3">
{t.conciergerieTitle}
</h3>
<p className="lead concierge-subheading-text">{t.conciergerieText}</p>
</div>
<div className="container">
<div className="row text-center mt-5">
{contentData?.map((item, index) => {
return (
<div className="col-md-4" key={index}>
<span className="fa-stack fa-4x">
<Image
layout="responsive"
src={myIcons[index]}
alt="icons"
className="svg-inline--fa fa-solid fa-stack-1x fa-inverse img-fluid"
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="house"
role="img"
objectFit="cover"
height={300}
width={300}
//loader={myLoader}
/>
</span>
<h4 className="my-3 text-hogar2 text-uppercase">
{item.title}
</h4>
<ul>
{item.text.map((text) => {
return (
<li key={text.id} className="list-unstyled">
<p className="m-0 text-muted text-list">
{text.content}
</p>
</li>
);
})}
</ul>
{item.id === "algomas" &&
(!showform ? (
<AiOutlinePlus
role="button"
onClick={() => {
setshowform(!showform);
}}
className="fs-2"
fill="#5ab4ab"
/>
) : (
<AiOutlineMinus
role="button"
onClick={() => {
setshowform(!showform);
}}
className="fs-2"
fill="#5ab4ab"
/>
))}
{item.id === "else" &&
(!showform ? (
<AiOutlinePlus
role="button"
onClick={() => {
setshowform(!showform);
}}
className="fs-2"
fill="#5ab4ab"
/>
) : (
<AiOutlineMinus
role="button"
onClick={() => {
setshowform(!showform);
}}
className="fs-2"
fill="#5ab4ab"
/>
))}
</div>
);
})}
</div>
{showform && showContactForm()}
</div>
</div>
);
};
export default Conciergerie;
can someone help me please?
The reason this problem is happening has to do with absolute and relative paths.
fetch("api/contact")
Is a relative path. The fetch function figures out the path of the current file, ie 3000/ourServices/conciergerie, and adds api/contact to it
On the other hand, if you add a "/" before the path :
fetch("/api/contact")
Fetch figures out the root path of the project, then adds the path you added, ie :
3000/api/contact
TL;DR: Change fetch("api/contact") to fetch("/api/contact").
This is MasterExcelService.js
import axios from 'axios';
const MASTEREXCEL_API_BASE_URL = "http://localhost:8080/api/masterexcel";
class MasterExcelService{
getMasterExcel(){
return axios.get(MASTEREXCEL_API_BASE_URL);
}
}
export default new MasterExcelService();
This is MasterExcelModule.jsx
import React, { Component } from 'react';
import MasterExcelService from '../services/MasterExcelService';
import HeaderComponent from './HeaderComponent';
class MasterExcelModule extends Component {
constructor(props) {
super(props)
this.state = {
masterexcel: []
}
}
componentDidMount(){
MasterExcelService.getMasterExcel().then((res) => {
this.setState({ masterexcel: res.data});
console.log(res.data);
});
}
render() {
return (
<div>
<HeaderComponent/>
<h2 className='text-center'>Master Excel Module</h2>
<div className = 'row'>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th>Serial Number</th>
<th>Banner</th>
<th>Chain</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.masterexcel.map(
master =>
<tr key = {master.excelID}>
<td>{master.excelID}</td>
<td>{master.banner}</td>
<td>{master.pChain}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default MasterExcelModule;
This is LoginComponent.jsx
class LoginComponent extends Component {
constructor(props) {
super(props);
this.state = this.initialState;
this.isValid = false
this.validateUser = this.validateUser.bind(this);
}
initialState = {
userID:'', password:'', error:'', loggedIn: false
};
credentialChange = event => {
this.setState({
[event.target.name] : event.target.value
});
};
validateUser = () => {
let user = {
userID: this.state.userID,
password: this.state.password,
};
UserService.loginUser(user).then((res) => {
if(res.data ==='SUCCESS') {
window.sessionStorage.setItem("isUserLogged", true);
this.props.history.push({ pathname: "/master-excel" });
} else if(res.data === 'FAILURE') {
this.resetLoginForm();
window.sessionStorage.setItem("isUserLogged", false);
this.setState({error:"Invalid User ID or Password, please try again!"});
}
})
};
resetLoginForm = () => {
this.setState(() => this.initialState);
};
render() {
const {userID, password, error} = this.state;
return (
<div>
<br></br>
<br></br>
<Row className="justify-content-md-center">
<Col xs={"auto"}>
{error && <Alert variant="danger">{error}</Alert>}
<Card>
<Card.Header className={"border border-light bg-light text-black"}>
<FontAwesomeIcon icon={faSignInAlt}/> Login
</Card.Header>
<br></br>
<form>
<label>
User ID:
<input type="text" name="userID" value={userID} onChange={this.credentialChange} />
</label>
<label>
Password:
<input type="password" name="password" value={password} onChange={this.credentialChange} />
</label>
<Button type="Submit" variant = "outline-success" onClick={this.validateUser} disabled={this.state.userID.length === 0 || this.state.password.length === 0}>Login</Button>
<Button type= "reset" variant = "outline-primary"onClick={this.resetLoginForm}>Reset</Button>
</form>
<br></br>
</Card>
</Col>
</Row>
</div>
);
}
}
export default (LoginComponent);
This is the LandingPage.jsx - Home Page
class LandingPage extends Component {
constructor(props){
super(props)
this.masterExcel = this.masterExcel.bind(this);
this.login = this.login.bind(this);
}
masterExcel(){
this.props.history.push('/master-excel');
}
login(){
this.props.history.push('/login');
}
render() {
return (
<div>
<h1> THIS IS THE LANDING PAGE </h1>
<Button size="sm" type="button" variant="success" onClick={this.login}>
Login
</Button>
{` `}
<Button size="sm" type="button" variant="success" onClick={this.masterExcel}>
Master Excel
</Button>
</div>
);
}
}
export default LandingPage;
This is App.js
function App() {
return (
<div>
<Router>
<div className='container'>
<Switch>
<Route path = "/" exact component={LandingPage}></Route>
<Route path = "/login" exact component={LoginComponent}></Route>
{/* <Route path = "/master-excel" exact component={MasterExcelModule}></Route> */}
<Route path = "/register" exact component={RegisterComponent}></Route>
<Route path="/master-excel" exact render={(props) => (
window.sessionStorage.getItem("isUserLogged") === "true"
? <MasterExcelModule {...props}/>
: <Redirect to='/login' />
)} />
</Switch>
</div>
</Router>
</div>
);
}
export default (App);
So, I am facing an issue with this code. I am trying to redirect the user to a new Component on successful login but the redirected component only stays for a split-second before I am redirected back to my Login Page.
When I open all the components through their links, they open just fine, it is only the redirection/ navigation that poses this problem. Where am I going wrong?
I am using react-router-dom v 5.2.0 and react version 17.0.2
I have solved this. The button type is set to "submit" in the LoginComponent, changing that to "button" instantly resolves the issue!
I've created a component to create follow and unfollow buttons and now I want to use this component in other components (like Suggestions).
In the suggestions component I want to show only the button that its value is equal to the user.id, but I am only able to get the 5 buttons from the original component.
Is there a way to select only the button that is equal to the user.id?
This is the component that creates the buttons:
render() {
const { users, followingUsers } = this.state
const userId = this.props.user[0].id
return(
<div>
{users.map((user, index) => {
if(userId !== user.id) {
if(followingUsers.includes(user.user_name)) {
return(
<Button key={index} value={user.id} onClick={this.onUnfollow}>Unfollow</Button>
)
} else {
return(
<Button key={index} value={user.id} onClick={this.onFollow}>Follow</Button>
)
}
}
})}
</div>
)
}
}
export default withUser(Unfollowfollow);
Here is the suggestions component:
render() {
const { users } = this.state
const userId = this.props.user[0].id
return (
<div>
<ul>
{users.map((user, index) => {
if(user.id !== userId) {
return (
<Card className="users" key= {index}>
<CardBody>
<CardImg className="picfollowers" top width="9%" src={user.image} />
<CardTitle onClick={() => this.handleClick(user.id)}>{user.user_name}</CardTitle>
<Unfollowfollow />
</CardBody>
</Card>
)}
})}
</ul>
</div>
)
}
}
export default withUser(Suggestions);
In this simple React App, I don't understand why I get the following warning message:
Warning: Each child in a list should have a unique "key" prop.
To me it seems that I put the key at the right place, in form of key={item.login.uuid}
How can I get rid of the warning message?
Where would be the right place to put the key?
App.js
import UserList from './List'
const App = props => {
const [id, newID] = useState(null)
return (
<>
<UserList id={id} setID={newID} />
</>
)
}
export default App
List.js
const UserList = ({ id, setID }) => {
const [resources, setResources] = useState([])
const fetchResource = async () => {
const response = await axios.get(
'https://api.randomuser.me'
)
setResources(response.data.results)
}
useEffect(() => {
fetchResource()
}, [])
const renderItem = (item, newID) => {
return (
<>
{newID ? (
// User view
<div key={item.login.uuid}>
<div>
<h2>
{item.name.first} {item.name.last}
</h2>
<p>
{item.phone}
<br />
{item.email}
</p>
<button onClick={() => setID(null)}>
Back to the list
</button>
</div>
</div>
) : (
// List view
<li key={item.login.uuid}>
<div>
<h2>
{item.name.first} {item.name.last}
</h2>
<button onClick={() => setID(item.login.uuid)}>
Details
</button>
</div>
</li>
)}
</>
)
}
const user = resources.find(user => user.login.uuid === id)
if (user) {
// User view
return <div>{renderItem(user, true)}</div>
} else {
// List view
return (
<ul>
{resources.map(user => renderItem(user, false))}
</ul>
)
}
}
export default UserList
The key needs to be on the root-level element within the loop. In your case, that's the fragment (<>).
To be able to do that, you'll need to write it out fully:
const renderItem = (item, newID) => {
return (
<Fragment key={item.login.uuid}>
{newID ? (
...
)}
</Fragment>
);
}
(You can add Fragment to your other imports from react).
Note that the fragment isn't actually needed in your example, you could drop it and keep the keys where they are since then the <div> and <li> would be the root element:
const renderItem = (item, newId) => {
return newID ? (
<div key={item.login.uuid}>
...
</div>
) : (
<li key={item.login.uuid}>
...
</li>
)
}
What if you create 2 separate components, one for the user view and one for the list item. That way you only need to pass the user prop. Also, use JSX and pass wht key from there.
const UserList = ({ id, setID }) => {
const [resources, setResources] = useState([])
const fetchResource = async () => {
const response = await axios.get(
'https://api.randomuser.me'
)
setResources(response.data.results)
}
useEffect(() => {
fetchResource()
}, [])
const User = ({user}) => (
<div key={user.login.uuid}>
<div>
<h2>
{user.name.first} {user.name.last}
</h2>
<p>
{user.phone}
<br />
{user.email}
</p>
<button onClick={() => setID(null)}>
Back to the list
</button>
</div>
</div>
)
const ListItem = ({user}) => (
<li key={user.login.uuid}>
<div>
<h2>
{user.name.first} {user.name.last}
</h2>
<button onClick={() => setID(user.login.uuid)}>
Details
</button>
</div>
</li>
)
const user = resources.find(user => user.login.uuid === id)
if (user) {
// User view
return <User user={user}</div>
} else {
// List view
return (
<ul>
{resources.map((user, index) => <ListItem key={index} user={user} />)}
</ul>
)
}
}
export default UserList