Properly LogOut button React - reactjs

can't get the logout button to work properly. I'm using React and Firebase.
Here is a portion of the code from App.js, where the function was declared
imports
import React, { useState, useEffect } from "react";
import { fire } from './fire';
import LogIn from './LogIn';
import Hero from './Hero';
import './App.css';
declaration
const handleLogout = () => {
fire.auth().signOut();
};
And here is the code from the Hero.js, where the function is used
import React from 'react';
import Contact from "./components/Contact";
const Hero = (handleLogout) => {
return(
<section className="hero">
<nav>
<h2>Welcome</h2>
<button onClick = {handleLogout}>Log Out</button>
</nav>
<div id="contact-form">
<Contact />
</div>
</section>
)
}
export default Hero;
What I'm doing wrong?

you need to get the handleLogout from props properly:
const Hero = ({handleLogout}) => {...}

Related

Is it possible to add an OnClick event in another component?

I added an OnClick event in a custom component created by me, but it didn't work. I want to add an OnClick event to this component. When i click it, it will play a youtube video below. Is it not possible to do this?
Here is my code:
import React, { useState } from "react";
import classes from "./Feature.module.css";
import { ButtonHorizontal, ButtonCircular } from "./Buttons";
function Feature() {
const [open, setOpen] = React.useState(false);
const openVideo = () => {
setOpen((prev) => !prev);
};
return (
<div>
<ButtonHorizontal icon={faPlay} text="Watch Video" onClick={openVideo}/>
{open ? (
<iframe
src="https://www.youtube.com/watch?v=k2qgadSvNyU"
frameborder="0"
allow="autoplay; encrypted-media"
allowfullscreen
title="video"
/>
) : null}
</div>
);
}
export default Feature;
And buttons.js:
import React from "react";
import classes from "./Buttons.module.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faPlay} from "#fortawesome/free-solid-svg-icons";
export function ButtonHorizontal(props) {
return (
<div className={classes.buttonHorizontal}>
<FontAwesomeIcon icon={props.icon} className={classes.icon}/>
<div className={classes.text}>{props.text}</div>
</div>
);
}
You need to attach the onClick property to an actual HTML element. Something like <div className={classes.buttonHorizontal} onclick={props.onClick}> should work.
import React from "react";
import classes from "./Buttons.module.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faPlay} from "#fortawesome/free-solid-svg-icons";
export function ButtonHorizontal(props) {
return (
<div className={classes.buttonHorizontal} onclick={props.onClick}>
<FontAwesomeIcon icon={props.icon} className={classes.icon}/>
<div className={classes.text}>{props.text}</div>
</div>
);
}

Testing react component

I have a simple app where I use an axios to get UserList from the API.
Here is my App component:
import React,{useState,useEffect} from 'react';
import axios from 'axios';
import UserList from './components/Users/UserList';
function App() {
const [users,setUsers] = useState([]);
useEffect(()=>{
axios.get('https://reqres.in/api/users?page=2')
.then(response =>{
setUsers(response.data.data);
console.log(response.data);
})
.catch(error =>{
console.log(error)
})
}, [])
return (
<div>
<UserList users={users} />
</div>
);
}
export default App;
And I have the UserList component:
import React from 'react';
import classes from './UserList.module.css';
import Card from '../UI/Card';
const UserList = (props) => {
return (
<Card className={classes.users}>
<ul data-testid="ultest">
{props.users.map(user => <li key={user.id}>
<img src={user.avatar} alt={user.id}></img>
<div>{user.first_name} {user.last_name}
<p><a href={`mailto:${user.email}`}>{user.email}</a></p>
</div>
</li>)}
</ul>
</Card>
)
}
export default UserList;
I don't understand how to test UserList component. I want to test if it renders correctly but I always get:
TypeError: Cannot read property 'map' of undefined
When I use render.
What is the best way to test this component? Jest or testing library.
Any advice would be appreciated.
import React from 'react';
import { render} from '#testing-library/react';
import UserList from '../components/Users/UserList';
import '#testing-library/jest-dom/extend-expect';
test('to check if it renders', () => {
render (<UserList />)
});
Hey – You need to do it like so:
test('to check if it renders', () => {
render(<UserList users={someUsersDataHere}/>)
});
So your component can have users to map over. You will need to manually define some array of users or import the data from elsewhere if you have it already by any chance
const someUsersDataHere = [
{name: 'SomeName'},
....and so on
]

How to change refs from one child component to other child component?

I am working on a chating app with reactjs and i have my components as:
-ChatBox
|-MessageList
|-InputArea
I want to update(re-render,basically append a "li" and scroll down automatically) MessageList component if user provides an input from Input Area.
What i have thought so far is to pass ref from chatbox to MessageList and and then use those refs in InputArea. But i think it is not a good approach. Can someone suggest me what to do.
Update:
My MessageList code:
import React, { useContext,useRef, useState, useEffect } from 'react';
import Message from './Message';
import "./MessageList.css";
import { AuthContext } from '../../Shared/Context/AuthContext';
const MESSAGES=[{convId:1, msgId:1 ,from:'u1',to:'u2',msg:"hello"},
{convId:1, msgId:2 ,from:'u2',to:'u1',msg:"hi"},
{convId:1, msgId:3 ,from:'u1',to:'u2',msg:"how ru"},
{convId:1, msgId:4 ,from:'u2',to:'u1',msg:"goood!!!"},
{convId:1, msgId:5 ,from:'u1',to:'u2',msg:"party ?!"},
{convId:1, msgId:6 ,from:'u2',to:'u1',msg:"yeah!!!"}];
const MessageList=(props)=>{
const msgBoxRef=useRef();
const [messages,setMessages]=useState(MESSAGES);
useEffect(()=>{
msgBoxRef.current.scrollTop=msgBoxRef.current.scrollHeight;
},[messages]);
useEffect(()=>{
if(msgBoxRef.current.scrollTop===msgBoxRef.current.scrollHeight)
msgBoxRef.current.scrollTop=msgBoxRef.current.scrollHeight;
},[])
const auth =useContext(AuthContext);
return (<div className="messages" ref={msgBoxRef}>
<ul>
{messages.map((msg)=>(
<Message key={msg.msgId} className={(msg.from===auth.user.userName)?"sent":"replies"} imageSrc="http://emilcarlsson.se/assets/mikeross.png">{msg.msg}</Message>
))}
</ul>
</div>);
};
export default MessageList;
Input Component code:
import React from 'react';
import {InputGroup,FormControl,Button} from 'react-bootstrap';
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faPaperPlane } from "#fortawesome/free-solid-svg-icons";
const Input=(props)=>{
return (<InputGroup className="mb-0">
<FormControl className="input-msg shadow-none" placeholder="Enter new message..." aria-label="new task" />
<InputGroup.Append>
<Button className="send-btn shadow-none">
<FontAwesomeIcon icon={faPaperPlane} />
</Button>
</InputGroup.Append>
</InputGroup>);
};
export default Input;
ChatBox code:
//TODO: IMPLEMENT CHAT CARD
import React, { useState, useRef } from "react";
import { Card } from "react-bootstrap";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faArrowLeft } from "#fortawesome/free-solid-svg-icons";
import MessageList from "./MessageList";
import Input from "./Input";
import Conversations from "./Conversations";
import "./ChatBox.css";
const ChatBox = (props) => {
const [conversation, setConversation] = useState(null);
const [backBtn,setBackBtn]=useState(false);
const selectedConv = (profile) => {
setConversation(profile);
setBackBtn(true);
};
const backBtnHandler=()=>{
setConversation(null);
setBackBtn(false);
}
return (
<Card className="frame">
{conversation ? (
<React.Fragment>
<Card.Header><FontAwesomeIcon icon={faArrowLeft} onClick={backBtnHandler}/>{" "+conversation.name}</Card.Header>
<MessageList chatId={conversation.id}/>
<Input />
</React.Fragment>
) : (
<React.Fragment>
<Card.Header>Chatbox</Card.Header>
<Conversations selectedChat={selectedConv} />
</React.Fragment>
)}
</Card>
);
};
export default ChatBox;

Reach Router: Components render only on refreshing the page right after navigating using Link tag

CodeSandbox https://codesandbox.io/s/billowing-hill-j5gmy?file=/src/App.js
import React from "react";
import "./App.css";
import Homepage from "./Components/Homepage";
import { Link, Router } from "#reach/router";
import Details from "./Components/Details";
function App() {
return (
<Router>
<Homepage path="/" />
<Details path="/details" />
</Router>
);
}
export default App;
The above is my app.js file , I am trying to navigate to details page using a Link tag in my Homepage component
import React, { Component } from "react";
import styled, { isStyledComponent } from "styled-components";
import Api from "../API/Accounts";
import { Link } from "#reach/router";
const Homepage = () => {
const [State] = Api("https://panorbit.in/api/users.json");
return (
<React.Fragment>
<div className={"container"}>
<div>
<h2>Select an Account</h2>
<div style={{ padding: 0 }}>
{State.map((item) => (
<Link to={"/details"}>
{}
<img src={item.profilepicture} alt="Girl in a jacket"></img>
<span>{item.name}</span>
</Link>
))}
</div>
</div>
</div>
</React.Fragment>
);
};
export default Homepage;
My issues is The details page dont render after navigating to /details page, Only if I refresh the page it renders properly.
Please help me out, beating my head over this one for few days
UPDATE
State is an Object that is returned when i call the API
import react, { useEffect, useState } from "react";
import axios from "axios";
const Api = (Api) => {
const [data, setData] = useState([]);
useEffect(async () => {
const result = await axios(Api).then((x) => setData(x.data.users));
}, []);
return [data];
};
export default Api;
think it should be:
<Details path="details" />
instead of
<Details path="/details" />

reactJs onClick handler not working

Although defining onClick handler properly, console.log('hi') is not printing on console
import React from 'react';
import './charComponent.css'
const CharOne = (props) =>{
return (<div>
<div className="charOne" onClick={console.log('hi')}>{props.letter}</div>
</div>
)
}
export default CharOne;
console.log('hi') is immediately invoking,
so your onClick has nothing to do (no job). See below code.
import React from 'react';
import ReactDOM from 'react-dom';
const myFunction = () => console.log('hi');
const CharOne = () => <div onClick={myFunction}>Click-Me</div>
ReactDOM.render(<CharOne />, document.getElementById('root'));
If you want to pass an argument, then use an arrow function.
import React from 'react';
import ReactDOM from 'react-dom';
const myFunction = props => console.log(props);
const CharOne = () => <div onClick={() => myFunction('Hello')}>Click-Me</div>
ReactDOM.render(<CharOne />, document.getElementById('root'));
You have to pass a function as parameter:
import React from 'react';
import './charComponent.css'
const CharOne = (props) =>{
return (<div>
<div className="charOne" onClick={() => console.log('hi')}>{props.letter}</div>
</div>
)
}
export default CharOne;

Resources