React: Props undefined when passed from Parent to Child Function Component - reactjs

I have an Chat application.
In the App.js function component I have a messages state initialized as an empty array.
import React, { useState, useEffect } from 'react';
import './App.css';
import Sidebar from './Sidebar';
import Chat from './Chat';
import Pusher from 'pusher-js';
import axios from './axios';
function App() {
const [messages, setMessages] = useState([]);
useEffect(() => {
axios.get('http://localhost:9000/messages/sync')
.then(response => {
console.log(response.data);
setMessages(response.data);
})
}, [])
// when function component loads, run the follow once
useEffect(() => {
const pusher = new Pusher('1693ef51485e86ca1e9f', {
cluster: 'us2',
});
const channel = pusher.subscribe('messages');
channel.bind('inserted', (newMessage) => {
alert(JSON.stringify(newMessage));
setMessages([...messages, newMessage]);
});
return () => {
channel.unbind_all();
channel.unsubscribe();
};
}, [messages])
return (
<div className="app">
<div className="app_body">
<Sidebar />
<Chat messsages={messages}/>
</div>
</div>
);
}
export default App;
Once messages are stored there, the messages state is passed down as props to a function component in Chat.js.
import { Avatar, IconButton } from '#material-ui/core';
import SearchOutlinedIcon from '#material-ui/icons/SearchOutlined';
import AttachFileIcon from '#material-ui/icons/AttachFile';
import MoreVertIcon from "#material-ui/icons/MoreVert";
import InsertEmoticonIcon from '#material-ui/icons/InsertEmoticon';
import MicIcon from '#material-ui/icons/Mic';
import React from 'react';
import './Chat.css';
function Chat({ messages }) {
console.log(messages)
return (
<div className="chat">
<div className="chat_header">
<Avatar />
<div className="chat_headerInfo">
<h3>Room Name</h3>
<p>Last seen at...</p>
</div>
<div className="chat_headerRight">
<IconButton>
<SearchOutlinedIcon />
</IconButton>
<IconButton>
<AttachFileIcon />
</IconButton>
<IconButton>
<MoreVertIcon />
</IconButton>
</div>
</div>
<div className="chat_body">
{console.log(messages)}
{/**messages.map((message) => {
<p className={`chat_message ${message.received && "chat_receiver"}`}>
<span className="chat_name">{message.name}</span>
{message.message}
<span className="chat_timestamp">
{message.timestamp}
</span>
</p>
}) */}
</div>
<div className="chat_footer">
<InsertEmoticonIcon />
<form>
<input placeholder="Type a message"
type="text"
/>
<button type="submit">
Send a message
</button>
</form>
<MicIcon />
</div>
</div>
)
}
export default Chat
However messages is undefined in Chat.
Where is the error? I've experimented with passing props to chat as:
function Chat (props) {
{console.log(props.message)}
}
Nothing seems to work.

Check the spelling tripple sss - messsages in
return (
<div className="app">
<div className="app_body">
<Sidebar />
<Chat messsages={messages}/>
</div>
</div>
);

It's quite possible that your request to localhost in the first useEffect hook is not returning a value with the response. Double check your console output on that. As written, it should be working.
If that seems perfectly fine, then I would say that you need to clear your build cache.

Related

React : The path to the "404 not found" page if there is an error does not work

I am trying to redirect to an error page if a product ID is not found in a React project. I then find myself faced with a blank page and this error:
I created a Hook with UseEffect to retrieve data from an API
And here is the code for the page that should either return the products or the error page:
import React from "react";
import { useParams } from "react-router-dom";
import Rating from "../../Components/Rating";
import Slider from "../../Components/Slider";
import Tags from "../../Components/Tags";
import Host from "../../Components/Host";
import Error from "../Error";
import Accordion from "../../Components/Accordion";
import "./logement.css";
import { useFetch } from "../../utils/hooks";
function Logement() {
const { logementId } = useParams();
const {
data: logement,
isLoading,
error,
} = useFetch(`http://localhost:8000/logements/${logementId}`);
if (isLoading) return <h1>LOADING...</h1>;
if (error) {
return <Error />;
}
return (
<div className="logements__page">
<div className="logements__wrapper">
<Slider slides={logement.pictures} />
<div className="content">
<div className="informations">
<h1>{logement.title}</h1>
<p className="logement__location">{logement.location}</p>
<div className="tags__wrapper">
{logement.tags.map((tag, index) => (
<Tags key={index} getTag={tag} />
))}
</div>
</div>
<div className="rating__host">
<Rating rating={logement.rating} />
<Host host={logement.host} />
</div>
</div>
<div className="collapsible">
<Accordion title="Description" content={logement.description} />
<Accordion title="Equipement" content={logement.equipments} />
</div>
</div>
</div>
);
}
export default Logement;
Thank you for your answers
{(logement?.tags || []).map((tag, index) => (
Try it, and your problem will be solved!

Error : "createSliderWithTooltip is not a function"

Im trying to implement the rc-slider for the web app however the rc-slider tooltip isnt recognized and shows an error of "createSliderWithTooltip is not a function" , which im not sure why .
For implementation of rc-slider i followed the rc-slider documentation which is the same way i have implemeneted in the code of home.js somehow im getting an error in console and nothing shows at all.
Thanks in advance.
Home.js
import React, { Fragment, useEffect , useState } from 'react'
import MetaData from './layouts/MetaData'
import { useDispatch , useSelector } from 'react-redux'
import { getProducts } from '../actions/products'
import Product from './products/Products'
import Loader from './layouts/Loader'
import { useAlert } from 'react-alert'
import Pagination from "react-js-pagination";
import {useParams} from 'react-router-dom'
import Slider from 'rc-slider'
import 'rc-slider/assets/index.css';
const { createSliderWithTooltip } = Slider;**//Error occurs here**
const Range = createSliderWithTooltip(Slider.Range)
const Home = () => {
const [currentPage,setCurrentPage]=useState(1);
const [price,setPrice]=useState([1,1000]);
let params=useParams();
const dispatch= useDispatch();
const alert=useAlert();
const {loading,products,error,productsCount,resPerPage,filteredProductsCount }= useSelector(state=>state.products)
const keyword=params.keyword;
useEffect(() => {
if (error) {
return alert.error("error");
}
dispatch(getProducts(keyword, currentPage));
}, [dispatch, alert, error, currentPage, keyword]);
function setCurrentPageNo(pageNumber) {
setCurrentPage(pageNumber)
}
return (
<Fragment>
{loading ? <Loader>Loading ...</Loader>:(
<Fragment>
<MetaData title={'Buy Electronics , Household Items and Many Others Online'} />
<h1 id="products_heading">Latest Products</h1>
<section id="products" className="container mt-5">
<div className="row">
<Fragment>
<div className="col-6 col-md-3 mt-5 mb-5">
<div className="px-5">
<Range
marks={{
1: `$1`,
1000: `$1000`
}}
min={1}
max={1000}
defaultValue={[1, 1000]}
tipFormatter={value => `$${value}`}
tipProps={{
placement: "top",
visible: true
}}
value={price}
onChange={price => setPrice(price)}
/>
</div>
</div>
</Fragment>
{products.map(product => (
<Product key={product._id} product={product} col={4} />
))}
</div>
</section>
<div className="d-flex justify-content-center mt-5">
<Pagination
activePage={currentPage}
itemsCountPerPage={resPerPage}
totalItemsCount={productsCount}
onChange={setCurrentPageNo}//sets current page no as it changes for state management
nextPageText={'Next'}
prevPageText={'Prev'}
itemClass="page-item"
linkClass="page-link"
/>
</div>
</Fragment>
)
}
</Fragment>
)}
export default Home
Instead of const { createSliderWithTooltip } = Slider;, try this:
const createSliderWithTooltip = Slider.createSliderWithTooltip;
I tried several ways and the only thing that actually worked was downgrading to 9.6.5 rc-slider and now everything is working perfectly
The document hasn't been updated yet since new version. As it seems you want to use Range component, now here the way to do it (thanks to Ashvin-Pal): https://github.com/react-component/slider/issues/825#issuecomment-1084416952
The createSliderWithTooltip has been removed in the new version.
Instead, you can implement your custom handle or tooltip easily like this:
handleRender={renderProps => {
return (
<div {...renderProps.props}>
<SliderTooltip>{round}%</SliderTooltip>
</div>
);
}}
let me know if you have any questions.

React routes not rendering the specific component

I am trying to make a WhatsApp Web clone using React and Firebase. Here I want to implement the functionality where clicking on a specific chat in the sidebar on left of window opens a chat body on right.
For this I am using Switch and Route in React. By default, I want to show the sidebar in all cases but display the Chat body only when the user clicks on one of the chats.
For this the code in my App.js is :
import React from "react";
import Chat from "./Chat";
import { BrowserRouter,Switch, Route } from "react-router-dom";
import "./App.css";
import Sidebar from "./Sidebar";
function App() {
return (
<div className="app">
<div className="app_body">
<BrowserRouter>
<Switch>
<Sidebar />
<Route exact path="/" component={Chat} />
<Route path="/rooms/:roomId" component={Chat} />
</Switch>
</BrowserRouter>
</div>
</div>
);
}
export default App;
However, only the sidebar gets displayed every time.The chat doesn't get displayed even when I have added the component Chat in my exact home route ("/")
as shown here
When I interchange the Chat and Sidebar components in the code, only the Chat component gets displayed like this
What is wrong in this code? I tried to search for a lot of answers but couldn't find any answers to this. I tried switching routes, components and everything
The codes for my specific components are :
Chat :
import React, { useState, useEffect } from "react";
import "./Chat.css";
import { Avatar, IconButton } from "#material-ui/core";
import {
Search,
AttachFile,
MoreVert,
InsertEmoticon,
Mic,
} from "#material-ui/icons";
import { useParams } from "react-router-dom";
import db from "./firebase";
function Chat() {
const [input, setInput] = useState("");
const { roomId } = useParams();
const [roomName, setRoomName] = useState("");
useEffect(() => {
if (roomId) {
db.collection("rooms")
.doc(roomId)
.onSnapshot((snapshot) => setRoomName(snapshot.data().name));
}
}, [roomId]);
const sendMessage = (e) => {
e.preventDefault();
console.log(input);
setInput("");
};
return (
<div className="chat">
<div className="chat_header">
<Avatar src="https://res.cloudinary.com/shatadrucld/image/upload/v1597305602/qpqnqwyuokbupddqwuwc.jpg" />
<div className="chat_headerInfo">
<h3>{roomName}</h3>
<p>Last seen at .....</p>
</div>
<div className="chat_headerRight">
<IconButton>
<Search />
</IconButton>
<IconButton>
<AttachFile />
</IconButton>
<IconButton>
<MoreVert />
</IconButton>
</div>
</div>
<div className="chat_body">
<p className={`chat_message ${true && "chat-receiver"}`}>
<span className="chat_name">Shatadru Roy</span>Hey guys
<span className="chat_timestamp">3:52pm</span>
</p>
</div>
<div className="chat_footer">
<InsertEmoticon />
<form>
<input
type="text"
placeholder="Type a message"
value={input}
onChange={(e) => {
setInput(e.target.value);
}}
></input>
<button type="submit" onClick={sendMessage}></button>
</form>
<Mic />
</div>
</div>
);
}
export default Chat;
Sidebar :
import SidebarChat from "./SidebarChat";
import db from "./firebase";
function Sidebar() {
const [rooms, setRooms] = useState([]);
useEffect(() => {
const unsubscribe=db.collection("rooms").onSnapshot((snapshot) => {
setRooms(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
);
});
return ()=>{
unsubscribe();
}
}, []);
return (
<div className="sidebar">
<div className="sidebar_header">
<Avatar />
<div className="sidebar_headerRight">
<IconButton>
<DonutLarge />
</IconButton>
<IconButton>
<Chat />
</IconButton>
<IconButton>
<MoreVert />
</IconButton>
</div>
</div>
<div className="sidebar_search">
<div className="sidebar_searchContainer">
<SearchOutlined />
<input placeholder="Seacrh chats" type="text"></input>
</div>
</div>
<div className="sidebar_chats">
<SidebarChat addNewChat />
{rooms.map(room=>{
return (<SidebarChat key={room.id} id={room.id} name={room.data.name} />)
})}
</div>
</div>
);
}
export default Sidebar;
Please help me with this problem. I am new to these concepts so I am completely stuck at this phase. I tried several solutions in the internet but none of them is working.
Edit :
I also tried to use withRouter but it is not working either
Try moving <Sidebar /> out of the <Switch> component. If is persistent then it should be outside of <Switch/>

not able to display console data in web page

i am beginner in react . when i fetch request from API, i got data in console ,but when i am trying to display data in web page in that time data isn't show.
I want to display data in web page.
here is my console log
https://ibb.co/YLmLQz1
App.js
import React from 'react';
import './App.css';
import Header from './components/Header';
import Movie from './components/Movies';
const App = () => {
return (
<div className="App">
<Header />
<div className='container'>
<Movie />
</div>
</div>
);
}
export default App;
Header.js
In header file i created my navbar and search form
import React, { useState } from 'react'
const Header = () => {
const [search, setSearch] = useState('');
return (
<div className="jumbotron">
<h1 className="display-1">
<i className="material-icons brand-icon">LatestMovie</i> Movie
</h1>
<div className="input-group w-50 mx-auto">
<input
type="text"
className="form-control"
placeholder="Search Your Movie..."
value={search}
onChange={e => setSearch(e.target.value)}
/>
<div className="input-group-append">
<button className="btn btn-dark">
Search Movie
</button>
</div>
</div>
</div>
)
}
export default Header;
Movies.js
here i fetch my movies request throght axios
import React, { useEffect, useState } from 'react'
import Axios from 'axios';
const Movie = () => {
const [movies, setMovie] = useState([]);
const apiurl = "http://www.omdbapi.com/?apikey=642b793e&s=marvel"
const getMovies = async () => {
const res = await Axios.get(apiurl);
console.log(res);
setMovie(res.data.hits);
}
useEffect(() => {
getMovies();
}, []);
return (
<div className='row'>
{
movies && movies.map(movie => (
<div className='col-md-3'>
<div className='card'>
<div className='card-body'>
<h4>{movie.Year}</h4>
</div>
</div>
</div>
))
}
</div>
)
}
export default Movie;

How to call a React hook function and pass data to Redux store in one onClick event?

I am trying to make a component that changes a color and passes it's value to Redux store but I am having difficulties implementing it.
When I add one function that changes color to onClick event, it works. When I add second function that passes value, only second function executes.
I have tried to place both functions in another function but it didn't work.
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import * as actionTypes from "../../store/Actions";
import { CSSTransition } from "react-transition-group";
import "./Shirts.scss";
import white from "../../assets/white.jpg";
import black from "../../assets/black.jpg";
import grey from "../../assets/grey.jpg";
const shirts = { white, black, grey };
function Shirts() {
const [selected, setSelected] = useState(shirts.black);
const selectedPoster = useSelector(state => state.poster);
const dispatch = useDispatch();
const passColor = e =>
dispatch({ type: actionTypes.PASS_COLOR, payload: e.currentTarget.value });
const changeColor = () => {
setSelected(shirts.white);
};
return (
<div>
<div className="shirts">
<CSSTransition
in={true}
key={shirts}
appear={true}
timeout={300}
classNames="fade"
>
<img alt="T-Shirt" className="shirt" src={selected} />
</CSSTransition>
</div>
<div>
<img className="selected-poster" alt="Poster" src={selectedPoster} />
</div>
<div className="color-picker">
<button
className="white-button"
value="White"
onClick={(changeColor, passColor)}
>
<p className="white-text">
W<br />
H<br />
I<br />
T<br />E
</p>
</button>
<button
className="grey-button"
value="Grey"
onClick={(() => setSelected(shirts.grey), passColor)}
>
<p className="grey-text">
G<br />
R<br />
E<br />Y
</p>
</button>
<button
className="black-button"
value="Black"
onClick={(() => setSelected(shirts.black), passColor)}
>
<p className="black-text">
B<br />
L<br />
A<br />
C<br />K
</p>
</button>
</div>
</div>
);
}
export default Shirts;
the correct syntax is:
onClick={((e) => setSelected(shirts.grey), passColor(e))}

Resources