How do I connect Posts to Upvotes - ReactJS - javascript

I have a laravelapi that fetches posts from the database and another one that fetches upvotes.
Now I want to display posts on my react component and show the length of upvotes for every particular post.
Here is how I have tried it out. But im getting the value as undefined on the console. Please help. Here is my code
import React, { useState, useEffect } from 'react';
import { useNavigate } from "react-router-dom";
import Menubar from "../../components/menubar/Menubar"
import PostSkeleton from '../../components/skeleton/PostSkeleton';
import PostWidget from '../../components/widgets/PostWidget';
import axios from 'axios';
function Community() {
let navigate = useNavigate();
const [posts, setPosts] = useState([]);
const [upvotes, setUpvotes] = useState([]);
const [limit, setLimit] = useState(4);
const [isLoading, setIsLoading] = useState(true);
const [loading, setLoading] = useState(false);
function handleClick() {
navigate("/add-post");
}
useEffect(() => {
let isMounted = true;
axios.get(`/api/posts?page=1&limit=` + limit).then(res => {
if (isMounted) {
if (res.data.status === 200) {
setPosts(res.data.posts);
setIsLoading(false);
setLoading(false);
}
}
});
return () => {
isMounted = false
};
}, [limit]);
const loadMore = () => {
setLimit(limit + 4)
setLoading(true);
}
useEffect(() => {
let isMounted = true;
axios.get(`/api/upvotes`).then(res => {
if (isMounted) {
if (res.data.status === 200) {
setUpvotes(res.data.upvotes);
}
}
});
return () => {
isMounted = false
};
}, []);
return (
<div>
<Menubar />
<div className="appHeader bg-primary text-light">
<div className="left">
<a onClick={() => navigate(-1)} className="headerButton goBack">
<i className="fi fi-rr-angle-left"></i> </a>
</div>
<div className="pageTitle">Community</div>
<div className="right">
<a href="#" className="headerButton">
<i className="fi fi-rr-paper-plane"></i> </a>
</div>
</div>
<div id="appCapsule">
<div className="section">
<div className="post-input mt-3">
<form>
<a href="profile.php" className="btn btn-icon btn-secondary rounded mr-1" >
<img src="assets/img/sample/avatar/avatar4.jpg" alt="avatar" className="avatar imaged rounded" />
</a>
<div className="form-group boxed">
<div className="input-wrapper">
<input type="text" onClick={handleClick} className="form-control" placeholder="Tell the World Something" />
</div>
</div>
</form>
</div>
</div>
<div className="section mt-2 mb-3">
{isLoading && <PostSkeleton cards={4} />}
{posts.map((post) => (<PostWidget post={post} upvotes={upvotes.find(upvotes =>posts.postid === upvotes.post_id)} key={post.postid} />))}
<div className="text-center">
<a onClick={loadMore} className={limit <= posts.length ? 'btn btn-text-primary mr-1' : 'btn btn-text-primary mr-1 disabled'} >{loading ? <><span className="spinner-border spinner-border-sm mr-05" role="status" aria-hidden="true"></span>Loading More</> : <>{limit <= posts.length ? <>Load More <i className="fi fi-rr-angle-small-right"></i></> : 'All Posts Loaded'} </>}</a>
</div>
</div>
</div>
</div>
);
}
export default Community;
The PostWidget Component
import React, { useState, useEffect } from 'react';
import { Link } from "react-router-dom";
import { LazyLoadImage } from "react-lazy-load-image-component";
import axios from 'axios';
import toast, { Toaster } from 'react-hot-toast';
const PostWidget = ( {post, upvotes}) => {
console.warn(upvotes && upvotes.length)
const formatDate = (dateString) => {
const options = { year: "numeric", month: "long", day: "numeric" }
return new Date(dateString).toLocaleDateString(undefined, options)
}
return (
<div>
<Toaster />
<div className="comment-block mb-3 pb-1">
<div className="comment-header">
<div className="avatar">
<img src="assets/img/sample/avatar/avatar1.jpg" alt="avatar" className="imaged w32 rounded mr-1" />
</div>
<div className="comment-other">
<h4 className="title">{post.user && post.user.firstname} {post.user && post.user.lastname}</h4>
<span className="time">{formatDate(post.created_at)}</span>
</div>
</div>
<div className="item">
<div className="in">
<div className="post-image mt-1">
<Link to={"/post-details/" + post.postid}>
<LazyLoadImage src={`http://localhost:8000/${post.postimage}`} alt="avatar" className="imaged w-100" />
</Link>
<Link to={"/fruit-details/" + post.fruit.id}>
<div className="chip mt-1 mr-1">
<span className="chip-label">{post.fruit.name}</span>
</div>
</Link>
</div>
<Link to={"/post-details/" + post.postid}>
<div className="text mt-1">
{post.postcontent}
</div>
</Link>
<div className="comment-footer">
<a href="" className="comment-button">
<i className="fi fi-rr-check"></i>
Upvote (5)
</a>
<a href="" className="comment-button">
<i className="fi fi-rr-arrow-down"></i>
Downvote
</a>
<Link to={"/post-details/" + post.postid} className="comment-button" >
<i className="fi fi-rr-comment"></i>
Comment
</Link>
</div>
</div>
</div>
</div>
</div>
);
}
export default PostWidget;

upvotes={upvotes.find(upvotes =>posts.postid === upvotes.post_id)}
I think you need to use post.postId instead of posts.postid

This seems likely to be incorrect:
upvotes.find(upvotes =>posts.postid === upvotes.post_id)
Probably you meant to use the post being iterated over in the predicate, not the posts collection.
upvotes.find(upvote =>post.postid === upvote.post_id)

Related

react_devtools_backend.js:4012 Warning: Cannot update a component (`ShowScore`) while rendering a different component (`NodeGroup`)

import React, { useEffect, useState } from "react";
import { useNavigate } from 'react-router-dom';
import PropTypes from "prop-types";
import { withTranslation } from "react-i18next";
import { FaCheck, FaTimes } from "react-icons/fa";
import { CircularProgressbarWithChildren, buildStyles } from "react-circular-progressbar";
import { easeQuadInOut } from "d3-ease";
import AnimatedProgressProvider from "../../../utils/AnimatedProgressProvider";
import "react-circular-progressbar/dist/styles.css";
import { useSelector } from "react-redux";
import { sysConfigdata } from "../../../store/reducers/settingsSlice";
function ShowScore({ t, score, totalQuestions, onPlayAgainClick, onReviewAnswersClick, onNextLevelClick, coins, quizScore, currentLevel, maxLevel, reviewAnswer, playAgain, nextlevel }) {
const [perValue, setPerValue] = useState(0);
const navigate = useNavigate();
const percentage = (score * 100) / totalQuestions;
// store data get
const userData = useSelector((state) => state.User);
const systemconfig = useSelector(sysConfigdata);
const goToHome = () => {
navigate("/");
};
const goBack = () => {
navigate("Quizplay");
};
// server image error
const imgError = (e) => {
e.target.src = "/images/user.webp"
}
return (
<React.Fragment>
<div className="score-section text-center bold">
{percentage >= Number(systemconfig.maximum_coins_winning_percentage) ? (
<>
<h4 className="winlos">
<b>{t("Winner")}</b>
</h4>
<h5 >{t("Congratulations")}</h5>
</>
) : (
<>
<h4 className="winlos">
<b>{t("Defeat")}</b>
</h4>
<h5 >{t("Better Luck Next Time")}</h5>
</>
)}
</div>
<div className="my-4 row d-flex align-items-center">
<div className="col-md-5 col-4 coin_score_screen ">
<h4 className=" score-circle-title">{t("Coins")}</h4>
<div className="score-circle ml-auto">
<CircularProgressbarWithChildren value={0} strokeWidth={5} styles={buildStyles({trailColor: '#f8c7d8'})}>
<h4 className=" mb-0">{coins ? coins : "0"}</h4>
</CircularProgressbarWithChildren>
</div>
</div>
<div className="col-md-2 col-4 coin_score_screen score-section text-center bold">
<div className="d-inline-block">
<AnimatedProgressProvider valueStart={0} valueEnd={percentage} duration={0.2} easingFunction={easeQuadInOut}>
{(value) => {
const roundedValue = Math.round(value);
setPerValue(roundedValue);
return (
<CircularProgressbarWithChildren
value={value}
strokeWidth={5}
styles={buildStyles({
pathTransition: "none",
textColor: "#ef5488",
trailColor: '#f5f5f8',
pathColor: percentage >= Number(systemconfig.maximum_coins_winning_percentage) ? "#15ad5a" : "#ef5488",
})}
>
<img src={userData.data && userData.data.profile ? userData.data.profile : process.env.PUBLIC_URL + "/images/user.webp"} alt="user" className="showscore-userprofile" onError={imgError}/>
</CircularProgressbarWithChildren>
);
}}
</AnimatedProgressProvider>
</div>
</div>
<div className="col-md-5 col-4 coin_score_screen ">
<h4 className=" score-circle-title">{t("Score")}</h4>
<div className="score-circle">
<CircularProgressbarWithChildren value={0} strokeWidth={5} styles={buildStyles({trailColor: '#f8c7d8'})}>
<h4 className=" mb-0">{quizScore ? quizScore : "0"}</h4>
</CircularProgressbarWithChildren>
</div>
</div>
</div>
<div className="my-4 align-items-center d-flex">
<div className="col-4 col-md-5 right_wrong_screen text-end" title={t("Incorrect Answers")}>
<h1 className="score-badge bg-danger mb-0">
{/* {console.log("score",score,"totalquestions",totalQuestions)} */}
<FaTimes /> {totalQuestions - score + " / " + totalQuestions}
</h1>
</div>
<div className="col-4 col-md-2 right_wrong_screen text-center percent_value">
<h1 className="winlos percentage">{perValue}%</h1>
</div>
<div className="col-4 col-md-5 right_wrong_screen text-start" title={t("Correct Answers")}>
<div className="score-badge bg-success">
<FaCheck />
<span> {score + " / " + totalQuestions}</span>
</div>
</div>
</div>
<div className="dashoptions row text-center">
{percentage >= Number(systemconfig.maximum_coins_winning_percentage) && maxLevel !== String(currentLevel) ? (
nextlevel ? (
<div className="fifty__fifty col-12 col-sm-6 col-md-2 custom-dash">
<button className="btn btn-primary" onClick={onNextLevelClick}>
{t("Next Level")}
</button>
</div>
) : (
""
)
) : playAgain ? (
<div className="fifty__fifty col-12 col-sm-6 col-md-2 custom-dash">
<button className="btn btn-primary" onClick={onPlayAgainClick}>
{t("Play Again")}
</button>
</div>
) : (
""
)}
{reviewAnswer ? (
<div className="audience__poll col-12 col-sm-6 col-md-2 custom-dash">
<button className="btn btn-primary" onClick={onReviewAnswersClick}>
{t("Review Answers")}
</button>
</div>
) : (
""
)}
<div className="resettimer col-12 col-sm-6 col-md-2 custom-dash">
<button className="btn btn-primary" onClick={goBack}>
{t("Back")}
</button>
</div>
<div className="skip__questions col-12 col-sm-6 col-md-2 custom-dash">
<button className="btn btn-primary" onClick={goToHome}>
{t("Home")}
</button>
</div>
</div>
</React.Fragment>
);
}
ShowScore.propTypes = {
score: PropTypes.number.isRequired,
totalQuestions: PropTypes.number.isRequired,
// coins: PropTypes.number.isRequired,
quizScore: PropTypes.number.isRequired,
// onPlayAgainClick: PropTypes.func.isRequired,
// onReviewAnswersClick: PropTypes.func.isRequired,
// onNextLevelClick: PropTypes.func.isRequired,
};
export default withTranslation()(ShowScore);
when i complete the quiz game and at end component call showscore.jsx and its running perfectly but in console throws error with badstate with setstate i cant understand please provide optimum solution to remove or solve this error if you contact me with email or get file of code i will send you just ping me on email sumi.mayani#gmail.com

How to get the name of the user that was clicked and send it to another component?

I'm having a problem that I can't solve. I have a component that is currently rendering the users that are in my database, which calls CarouselUsers.jsx, so far so good, it is showing correctly.
But my goal is that after I click on one of these users that were listed, his name appears in a sidebar, which is in another component, but I am not able to do that, can you help me?
CarouselUsers.jsx
import React, { useState, useEffect } from 'react';
import * as Styled from './style.jsx';
import {
collection,
getDocs,
} from "firebase/firestore";
import { Swiper, SwiperSlide } from "swiper/react";
import { db } from '../../Data/Firebase.jsx';
import "swiper/css";
import euTeste from '../../assets/teste.jfif'
import SideBarProfile from '../../components/SideBarProfile/SideBarProfile.jsx';
export default function CarouselUsers() {
const [profile, setProfile] = useState(false)
const openProfile = () => {
setProfile(profile => !profile)
}
// USERS IN THE DB
const [users, setUsers] = useState([])
const usersCollectionRef = collection(db, "usuarios")
useEffect(() => {
const getUsers = async () => {
const data = await getDocs(usersCollectionRef);
setUsers(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
getUsers();
}, []);
// USERS IN THE DB
return (
<>
<Styled.CarouselUsers>
{/* MEMBROS CARROSEL */}
<div className="boxMembros">
<div className="titulo">
<h6>Membros</h6>
</div>
<Swiper
spaceBetween={10}
slidesPerView={3}
>
{users.map((user) => {
return (
<>
<SwiperSlide>
<div className="box"style={{ background: `linear-gradient(to bottom,rgba(0, 0, 0, 0.4) 0,rgba(0,0,0,.6) 100%),url(${euTeste})` }} onClick={openProfile} key={user.nome}>
<div className="infoBottom">
<div className="info">
{/* GET THE USERNAME */}
<h6>{user.nome}</h6>
{/* GET THE USERNAME */}
</div>
</div>
</div>
</SwiperSlide>
</>
);
})}
</Swiper>
</div>
{/* MEMBROS CARROSEL */}
</Styled.CarouselUsers>
<SideBarProfile profile={profile} openProfile={openProfile} />
</>
)
}
SideBarProfile.jsx
import React from 'react'
import { XCircle,WhatsappLogo } from "phosphor-react";
import * as Styled from './style.jsx';
export default function SideBarProfile({openProfile,profile}) {
return (
<Styled.SideBarProfile>
<div className={profile ? 'col-md-3 boxLeftWrapper open' : 'col-md-3 boxLeftWrapper close'} profile={profile}>
<div className="boxAll">
<div className="header d-flex justify-between align-items-center">
<div className="titulo">
<h1>Perfil</h1>
</div>
<div className="close">
<button onClick={openProfile}>
<XCircle/>
</button>
</div>
</div>
<div className="boxBodyUser text-left">
<div className="boxThis">
<div className="foto">
<img alt="Usuário" className='img-fluid ativo' />
</div>
<div className="nome text-center">
<h5>{/* SHOW USERNAME */}</h5>
</div>
<div className="status ativo">
<span>Ativo</span>
</div>
<div className="ministerios">
<ul className="pl-0 list-none mb-0">
<li>Teatro</li>
<li>Mídias Sociais</li>
</ul>
</div>
<div className="boxContato mt-5">
<div className="whatsapp d-flex items-center justify-center gap-2">
<WhatsappLogo/>
<span>Mensagem</span>
</div>
</div>
</div>
</div>
</div>
</div>
</Styled.SideBarProfile>
)
}
You can add an onClick event in your CarouselUsers component that grab the Inner Text in <h6>{user.nome}</h6> and pass it as props to SideBarProfile component .
like this :
CarouselUsers.jsx :
export default function CarouselUsers() {
const [profile, setProfile] = useState(false)
const [selectedUser, setSelectedUser] = useState("")
const handleClick = (event) => {
setSelectedUser(event.target.innerText);
}
// rest of your code
return (
......
{/* GET THE USERNAME */}
<h6 onClick={handleClick} >{user.nome}</h6>
{/* GET THE USERNAME */}
.... rest of your code
<SideBarProfile profile={profile} openProfile={openProfile}
setSelectedUser = {setSelectedUser} />
)
}
SideBarProfile.jsx :
export default function SideBarProfile({openProfile,profile, setSelectedUser}) {
return (
......
<div className="nome text-center">
<h5>{setSelectedUser}</h5>
</div>
....
)

Error Functions are not valid as a React child. This can happen if you return a Component instead of <Component /> from render

I tell you that I am making a shopping cart and I get the following warning "Functions are not valid as a React child. This can happen if you return a Component instead of from render. Or maybe you meant to call this function instead of returning it.", what I am doing is passing through an event information to the father from the son to be used later in the Cart.
the codes are these:
ItemDetial (detail of the product selected by the customer):
import React, { useState } from "react";
import '../App.css';
import 'materialize-css/dist/css/materialize.css';
import Count from './ItemCount';
import { Link } from "react-router-dom";
export const ItemDetail = (({item}) => {
const [itemSell, setItemSell] = useState(false);
const onAdd = (count) => {
setItemSell(true);
}
return (
<>
{
<main className="row soloProduct" id= {item.id}>
<aside>
<img src={item.image} alt="item" className="itemImg responsive-img"/>
</aside>
<article>
<div className=" col s12 m8">
<h5 className="itemName">{item.title}</h5>
</div>
<div className="col s12 m4">
<p className="itemPrice"> {item.price}</p>
</div>
<div className="col s12 m12">
<p className="itemDescription">{item.description}</p>
</div>
<div className="col s12">
{
itemSell ? <Link to="/cart"><button className="waves-effect waves-light btn-large">Finalizar Compra</button></Link> : <Count stockInitial={5} onAdd= { onAdd } />
}
</div>
</article>
</main>
}
</>
)
});
export default ItemDetail;
ItemCount (it is a counter so that the client has the possibility of buying more than one product):
import React, { useState} from 'react';
import 'materialize-css/dist/css/materialize.css';
import '../App.css';
import {FontAwesomeIcon} from '#fortawesome/react-fontawesome';
import {faPlus, faMinus, faPowerOff} from '#fortawesome/free-solid-svg-icons';
const ItemCount = ({stockInitial, initial = 0, onAdd}) => {
const [contador, setContador] = useState(initial)
const [stock, setStock] = useState(stockInitial)
const sumar = () => {
setContador(contador + 1)
setStock(stock - 1);
avisarStock();
}
const restar= () => {
if(contador > 0){
setContador(contador - 1);
setStock(stock + 1);
}
else
{
setContador(0);
}
}
const reset = () =>{
setContador(0);
setStock(stockInitial);
}
const avisarStock = () => {
if(stock > 0 ){
}
else{
alert('No podemos enviar su envio no hay stock');
setStock(0);
setContador(contador)
}
}
const agregarAlCarrito = () => {
onAdd(contador);
}
return(
<>
<div className=" row left text">Stock: {stock}</div>
<article>{contador}</article>
<div className="buttonCount">
<button onClick={sumar}>
<FontAwesomeIcon icon ={faPlus}/>
</button>
<button onClick={restar}>
<FontAwesomeIcon icon={faMinus}/>
</button>
<button onClick={reset}>
<FontAwesomeIcon icon={faPowerOff}/>
</button>
<br/><h2>{avisarStock}</h2>
<button onClick={agregarAlCarrito}> Agregar al carrito </button>
</div>
</>
)
}
export default ItemCount;
if you can give me a hand
Thank you
Hey juan hope you're doing well..
I just found a single mistake that is your ( brackets in itemdetails component. check the same your code given below-
import React, { useState } from "react";
import '../App.css';
import 'materialize-css/dist/css/materialize.css';
import Count from './ItemCount';
import { Link } from "react-router-dom";
const ItemDetail = ({item}) => {
const [itemSell, setItemSell] = useState(false);
const onAdd = (count) => {
setItemSell(true);
}
return (
<>
{
<main className="row soloProduct" id= {item.id}>
<aside>
<img src={item.image} alt="item" className="itemImg responsive-img"/>
</aside>
<article>
<div className=" col s12 m8">
<h5 className="itemName">{item.title}</h5>
</div>
<div className="col s12 m4">
<p className="itemPrice"> {item.price}</p>
</div>
<div className="col s12 m12">
<p className="itemDescription">{item.description}</p>
</div>
<div className="col s12">
{
itemSell ? <Link to="/cart"><button className="waves-effect waves-light btn-large">Finalizar Compra</button></Link> : <Count stockInitial={5} onAdd= { onAdd } />
}
</div>
</article>
</main>
}
</>
)
};
export default ItemDetail;
If this works just lemme know. thanks

onClick of button triggering all the components to open - Reactjs

I implemented a Card component and basically generating a bunch of cards on some input data. I binded a setter function on button click on every card which basically expands and collapse it. Even after putting unique keys to the div is sort of triggering all the cards to open at once.
Here is the code piece:
import React, { useState } from 'react';
import PrettyPrintJson from './PrettyPrintJson';
import './Card.scss';
import '../App.scss';
const Card = (props) => {
const { data } = props;
const [collapse, toggleCollapse] = useState(true);
return (<div className="card-group">
{data.map((obj, idx)=>{
return <div className="card" key={`${idx}_${obj?.lastModifiedOn}`}>
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
</div>
</div>
<div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>
})}
</div>
);
}
export default Card;
Create a component that manages it's own state and render that component.
const CardItem = ({ obj }) => {
const [collapse, toggleCollapse] = useState(true);
return (<div className="card">
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
</div>
</div>
<div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>)
}
then render it like
{data.map((obj, idx)=> (<CardItem obj={obj} key={idx} />))}
I think you can declare a state which is a type of int. After then, you can use the if-statement of index(idx) and state.
Like this:
const [collapsedCardNumbers, toggleCollapseCard] = useState([]);
const addCardNumber = (idx, prevState) => {
const arr_cardNum = prevState
!arr_cardNum .includes(idx) && arr_cardNum .push(idx)
return arr_cardNum
}
...
{data.map((obj, idx)=>{
return <div className="card" key={`${idx}_${obj?.lastModifiedOn}`}>
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapseCard(prevState => addCardNumber(idx, prevState))}>Show Json</button>
</div>
</div>
<div className={`card-content ${collapsedCardNumbers.includes(idx) ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>
})}

React Hooks Problem: Unhandled Rejection (TypeError): Cannot read property 'signup' of undefined

I'm trying to implement the useAuth hook from https://usehooks.com/
useAuth.js
// Hook (use-auth.js)
import React, { useState, useEffect, useContext, createContext } from "react";
import axios from 'axios';
//Credentials
const authContext = createContext();
// Provider component that wraps your app and makes auth object ...
// ... available to any child component that calls useAuth().
export function ProvideAuth({ children }) {
const auth = useProvideAuth();
return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}
// Hook for child components to get the auth object ...
// ... and re-render when it changes.
export const useAuth = () => {
return useContext(authContext);
};
// Provider hook that creates auth object and handles state
function useProvideAuth() {
const [user, setUser] = useState(null);
const API_URL = "http://localhost:1038";
// Wrap any Firebase methods we want to use making sure ...
// ... to save the user to state.
const signin = (email, password) => {
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(response => {
setUser(response.user);
return response.user;
});
};
const register = (username, email, password) => {
return firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(response => {
setUser(response.user);
return response.user;
});
};
const signup = async (data) => {
const SIGNUP_ENDPOINT = `${API_URL}/wp-json/wp/v2/users/register`;
let response = '';
try {
response = await axios({
method: 'post',
responseType: 'json',
url: SIGNUP_ENDPOINT,
data: data
});
} catch(e){
console.log(e);
}
console.log(response);
};
const signout = () => {
return firebase
.auth()
.signOut()
.then(() => {
setUser(false);
});
};
const sendPasswordResetEmail = email => {
return firebase
.auth()
.sendPasswordResetEmail(email)
.then(() => {
return true;
});
};
const confirmPasswordReset = (code, password) => {
return firebase
.auth()
.confirmPasswordReset(code, password)
.then(() => {
return true;
});
};
// Return the user object and auth methods
return {
user,
signin,
signup,
register,
signout,
sendPasswordResetEmail,
confirmPasswordReset
};
}
Form register.js
import Link from 'next/link';
import Layout from '../components/layout';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faEnvelope, faCheck, faLock, faUser } from '#fortawesome/free-solid-svg-icons'
import useForm from 'react-hook-form'
import { useAuth } from "../hooks/useAuth";
export default function Register(props) {
// Get auth state and re-render anytime it changes
const auth = useAuth();
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = data => { auth.signup(data) }
return (
<Layout>
<div className="container mt-sm p-md">
<div className="columns">
<div className="column">
</div>
<div className="column">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="field">
<label className="label">Username</label>
<div className="control has-icons-left has-icons-right">
<input className="input is-success" type="text" placeholder="Username" name="username" ref={register({ required: true })}/>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faUser}/>
</span>
<span className="icon is-small is-right">
<FontAwesomeIcon icon={faCheck}/>
</span>
</div>
{errors.username && <p className="help is-danger">This username is invalid</p>}
</div>
<div className="field">
<label className="label">Email</label>
<div className="control has-icons-left has-icons-right">
<input className="input is-success" type="text" placeholder="Email" name="email" ref={register({ required: true , pattern: /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/})}/>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEnvelope}/>
</span>
<span className="icon is-small is-right">
<i className="fas fa-exclamation-triangle"></i>
</span>
</div>
{errors.email && <p className="help is-danger">This email is invalid</p>}
</div>
<div className="field">
<label className="label">Password</label>
<div className="control has-icons-left">
<input className="input" type="password" placeholder="Password" name="password" ref={register({ required: true , pattern: /^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})/ })}/>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faLock}/>
</span>
</div>
</div>
{errors.password && <p className="help is-danger">This password is too weak</p>}
<div className="field">
<label className="label">Confirm Password</label>
<div className="control has-icons-left">
<input className="input" type="password" placeholder="Confirm Password" name="confirm_password" ref={register({ required: true , validate: (value) => { return value === watch('password')} })}/>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faLock}/>
</span>
</div>
</div>
{errors.confirm_password && <p className="help is-danger">This password do not match</p>}
<div className="field">
<div className="control">
<label className="checkbox">
<input type="checkbox" name="terms" ref={register({ required: true })}/>
I agree to the <Link href='/'><a>terms and conditions</a></Link>
</label>
</div>
</div>
{errors.terms && <p className="help is-danger">You must agree to the terms and conditions</p>}
<div className="field is-grouped">
<div className="control">
<button className="button is-link">Submit</button>
</div>
<div className="control">
<button className="button is-link is-light" type="submit">Cancel</button>
</div>
</div>
</form>
</div>
<div className="column">
</div>
</div>
</div>
</Layout>
)
}
I'm getting the error when the form submits and I call the useAuth hook.
Unhandled Rejection (TypeError): Cannot read property 'signup' of undefined
onSubmit
./pages/register.js:15
12 | // Get auth state and re-render anytime it changes
13 | const auth = useAuth();
14 | const { register, handleSubmit, watch, errors } = useForm();
> 15 | const onSubmit = data => { auth.signup(data) }
| ^ 16 |
17 | return (
18 | <Layout>
Any ideas on where im going wrong. the hook was meant to be used with firebase but im modifying it for wordpress so only the signup function is set up right now.
Layout.js
import Head from 'next/head'
import Link from 'next/link'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faCoffee } from '#fortawesome/free-solid-svg-icons'
import '../styles/styles.sass'
import { ProvideAuth } from "../hooks/useAuth";
export default ({ children }) => {
const toggleStyles = (event) => {
document.querySelector('#burger').classList.toggle('is-active')
document.querySelector('#navbarmenu').classList.toggle('is-active')
}
return (
<ProvideAuth>
<div>
<Head>
<title>Quiz Client</title>
<meta name="viewport" content="initial-scale=1.0, width=device-
width"/>
</Head>
<header>
<nav className="navbar is-primary" role="navigation" aria-
label="main navigation">
<div className="navbar-brand">
<a className="navbar-item">
<FontAwesomeIcon icon={faCoffee} />
</a>
<a id="burger" onClick={toggleStyles}
role="button" className="navbar-burger burger" aria-
label="menu" aria-expanded="false" data-target="navbarmenu">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarmenu" className="navbar-menu">
<div className="navbar-start">
<Link prefetch href="/">
<a className="navbar-item">Home</a>
</Link>
<Link prefetch href="/elsewhere">
<a className="navbar-item">Elsewhere</a>
</Link>
</div>
<div className="navbar-end">
<Link prefetch href="/login">
<a className="navbar-item">Login</a>
</Link>
<Link prefetch href="/register">
<a className="navbar-item">Register</a>
</Link>
</div>
</div>
</nav>
</header>
{children}
<footer className="footer">
<div className="content has-text-centered">
<span>I'm the footer</span>
</div>
</footer>
</div>
</ProvideAuth>
)
}
Excuse the formatting
Your Register component is not wrapped by your ProvideAuth provider. You can fix this simply by rearranging your components slightly
function RegisterForm(props) {
// Get auth state and re-render anytime it changes
const auth = useAuth();
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = data => { auth.signup(data) }
return (
<div className="container mt-sm p-md">
{/* the rest of your form */}
</div>
)
}
export default function Register(props) {
return (
<Layout>
<RegisterForm />
</Layout>
)
}

Categories