Error : Object are not valid as a react child - javascript

I am Trying to loop through the data coming from database, but react is giving me this error
i have tried by rendering the list in seperate componet still it doesnot work!,i am beginner to react ecosystem.
fetched data look like-
and my page code is this-
import React, { useEffect, useState } from 'react';
import './account.scss';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { selectCurrentUser } from '../../reducer/user/user.selectors';
import Order from '../../models/order';
const AccountPage = ({ currentUser }) =>{
const[orders,setOrders]=useState([]);
useEffect(()=>{
const fetchFunc= async () =>{
try{
const response= await fetch(`https://orders-6exxx.firebaseio.com/userorders/${currentUser.id}.json`);
if(!response.ok){
throw new Error('Something Went Wrong!');
}
const resData= await response.json();
const loadedOrders=[];
for(const key in resData){
loadedOrders.push(
new Order(
key,
resData[key].cartItems,
resData[key].totalAmount,
new Date(resData[key].date)
));
}
setOrders(loadedOrders);
}catch(err){
throw err;
}
};
fetchFunc();
},[currentUser]);
console.log(orders);
return(
<div className='account'>
{orders&&orders.length ? (
<div className='account__container'>
{
orders.map(order =>(
<div className='account__containers__orders'>
<div className='account__containers__orders--date'>
{order.date}
</div>
{
order.items.map(item => (
<div className='account__containers__orders__item'>
<div>{item.name}</div>
<div>{item.quantity} x</div>
<div>{item.price}</div>
</div>
))
}
<div className='account__containers__orders--total'>
<span className='price--tag'>₹</span> {order.totalAmount}
</div>
</div>
))
}
</div>
) : (
<div className='orders-loading'>
No Orders
</div>
)}
</div>
);
};
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser
});
export default connect(
mapStateToProps
)(AccountPage);
single data is loading but when i try to print multiple data, it gives me this error

You store new Date() inside your orders state and it is treated ot be an object. In order to render it you can convert it to a string
{order.date.toString()}
or
{order.date.toDateString()}

Related

How to get value from an object of maps from Firestore

I want to access each map and their fields induvidually to pass it to a card
I tried the following code
import React, { useEffect, useState } from "react";
import Sidebar from "./Sidebar";
import Navbar from "./Navbar";
import MyStyledCard from "./RequestCard";
import CardList from "./RequestCard";
import { getDoc, doc } from "firebase/firestore";
import { db } from "../firebase";
export default function Requests() {
const [Data, setData] = useState([]);
const reg_no = "G2062059";
let list = [];
useEffect(() => {
const fetchData = async () => {
const docRef = doc(db, "meta", "project-ideas");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
setData(docSnap.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
};
// Data.map((anObjectMapped, index) => {
// console.log(anObjectMapped.name);
// });
fetchData();
}, []);
return (
<div className="requests_out">
<div className="requsts_side">
<Sidebar />
</div>
<div className="requests_main">
<Navbar />
<div className="widgets">
<h2>{Data[reg_no]}</h2>
</div>
</div>
</div>
);
}
It gives an error like this.
Uncaught Error: Objects are not valid as a React child (found: object with keys {grp_id, pTitle, status, pDescription}). If you meant to render a collection of children, use an array instead.
If i give console.log(Data) it gives an object like this
.
The fetch is correct, however you are trying to render a javascript object. This is not possible and invalid JSX.
Choose what property inside G2062059 you want to display
Invalid code:
<div className="widgets">
<h2>{Data[reg_no]}</h2> <--- THIS IS INVALID JSX
</div>
Valid code:
Render a property of an object (string)
<div className="widgets">
<h2>{Data[reg_no]?.status}</h2>
</div>

React: How to avoid duplication in a state array

I am making MERN social media app.
I want to show all the friends of the current user in a list in SideBar.jsx .
Home.jsx (parent of Sidebar.jsx)
import React, { Component } from "react";
import { Person } from "#material-ui/icons";
import Topbar from "../../components/topbar/Topbar";
import Sidebar from "../../components/sidebar/Sidebar";
import Feed from "../../components/feed/Feed";
import Rightbar from "../../components/rightbar/Rightbar";
import "./home.css";
export default function Home() {
return (
<>
<Topbar />
<div className="homeContainer">
<Sidebar />
<Feed />
<Rightbar />
</div>
</>
);
}
SideBar.jsx
import "./sidebar.css";
import React, { Component, useContext, useState } from "react";
...
import { axiosInstance } from "../../config";
export default function Sidebar() {
const { user } = useContext(AuthContext);
const [followings, setFollowings] = useState([]);
const followingsList = user.followings;
useEffect(() => {
const fetchFollowings = async () => {
followingsList.map(async (id) => {
try {
const theUser = await axiosInstance.get(`/users?userId=${id}`);
if (followings.includes(theUser.data)) {
} else {
setFollowings((prev) => [...prev, theUser.data]);
}
} catch (error) {
console.log(error);
}
});
};
fetchFollowings();
}, [user]);
return (
<div className="sidebar">
.....
<ul className="sidebarFriendList">
{followings.map((u) => (
<CloseFriend key={u._id} user={u} />
))}
</ul>
</div>
</div>
);
}
For example, in this case, in the state "followings", there are 2 user objects.
So, the line
followings.map((u) => (...
should only show 2 entries.
However, the result is below.
As you can see, it is showing each friend twice.
I tired to check if a user object already exists in followings by doing
if (followings.includes(theUser.data)) {
} else {
setFollowings((prev) => [...prev, theUser.data]);
}
But this is not working.
How can I make sure that it only shows each user once?
I want it to be like this
Any help would be greatly appreciated. thank you
This is happening because it seems that your useEffect method is being fired two times (probably because you are using React.StrictMode) and you are setting the state inside the .map method (that is not good because you trigger a new render each time you call the setState).
What I would recommend you to do, is to remove the setState from the .map method and just set the new state after you format your data. So it would be something like this:
const newFollowings = followingsList.map(async (id) => {
try {
const theUser = await axiosInstance.get(`/users?userId=${id}`);
return theUser.data;
} catch (error) {
console.log(error);
}
});
setFollowings(newFollowings);
Probably you would have to add a filtering to the array in case there are some errors (because on errors the mapped value would be undefined):
.filter(data => data);
When you are using the .map function with async/await Promise.all usually always does the trick. Instead of pushing the state on every iteration you collect the followers list and set the state when all your fetching is done. I did not test it yet, but I hope it works.
const followingsList = user.followings;
useEffect(() => {
const fetchFollowings = async () => {
const list = await Promise.all(followingsList.map(async (id) => (
await axios.get('/user?userId=' + id);
)));
setFollowers(list);
};
fetchFollowings();
}, [user]);
Note: let me know if it works, if not I'll do a little sandbox on my own

How to pass data from child to parent and render content based on selected value in dropdown?

I am learning React as I am fetching data from Pokéapi to make a list component, card component, detail component and filter component. I am trying to make a filter so you can filter by pokémon type. Only the cards that also contain that type string should then render (Not there yet). So I am not sure if a) I should make a different call from API inside PokemonList depending on selected value or b) if I should compare the values and just change how the PokemonCard element is rendered inside PokemonList.js depending on the comparison. I managed to pass data from filter to the list component. I have then been trying to pass the type data from PokemonCard.js to the list component so that I can compare these two values but I find it hard to use callbacks to pass the type data from the card component, since I dont pass it through an event or something like that.
Which method should I use here to simplify the filtering? Make different API call or render PokemonCard element conditionally?
Is it a good idea to compare filter option to pokemon card's type in PokemonList.js? Then how can I pass that data from the card component since I don't pass it through click event?
Thankful for any ideas! I paste the code from list component that contains the cards, card component and filter component.
PokemonList component:
import { useState } from 'react';
import useSWR from 'swr';
import PokemonCard from './PokemonCard';
import PokemonFilter from './PokemonFilter';
import './PokemonList.css';
const PokemonList = () => {
const [index, setIndex] = useState(0);
const [type, setType] = useState('');
function selectedType(type) { // value from filter dropdown
setType(type)
console.log("handled")
console.log(type)
}
const url = `https://pokeapi.co/api/v2/pokemon?limit=9&offset=${index}`;
const fetcher = (...args) => fetch(...args).then((res) => res.json())
const { data: result, error } = useSWR(url, fetcher);
if (error) return <div>failed to load</div>
if (!result) return <div>loading...</div>
result.results.sort((a, b) => a.name < b.name ? -1 : 1);
return (
<section>
<PokemonFilter onSelectedType={selectedType} selectedPokemonType={type} />
<div className="pokemon-list">
<div className="pokemons">
{result.results.map((pokemon) => (
<PokemonCard key={pokemon.name} pokemon={pokemon} /> // callback needed??
))}
</div>
<div className="pagination">
<button
onClick={() => setIndex(index - 9)}
disabled={result.previous === null}
>
Previous
</button>
<button
onClick={() => setIndex(index + 9)}
disabled={result.next === null}
>
Next
</button>
</div>
</div>
</section>
)
}
export default PokemonList;
PokemonCard component:
import { Link } from "react-router-dom";
import useSWR from 'swr';
import './PokemonCard.css';
const PokemonCard = ({ pokemon }) => {
const { name } = pokemon;
const url = `https://pokeapi.co/api/v2/pokemon/${name}`;
const { data, error } = useSWR(url);
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
const { types, abilities } = data;
// types[0].type.name <---- value I want to pass to PokemonList.js
return (
<div className='pokemon-card'>
<div className='pokemon-card__content'>
<img
className='pokemon-card__image'
src={data.sprites.front_default}
alt={name}
/>
<div className='pokemon-card__info'>
<p className='pokemon-card__name'>Name: {name}</p>
<p className='pokemon-card__abilities'>Abilities: {abilities[0].ability.name}</p>
<p className='pokemon-card__categories'>Category: {types[0].type.name}</p>
</div>
</div>
<Link className='pokemon-card__link' to={{
pathname: `/${name}`,
state: data
}}>
View Details
</Link>
</div>
)
}
export default PokemonCard;
PokemonFilter component:
import './PokemonFilter.css';
import useSWR from 'swr';
const PokemonFilter = ({onSelectedType, selectedPokemonType}) => {
const url = `https://pokeapi.co/api/v2/type/`;
const fetcher = (...args) => fetch(...args).then((res) => res.json())
const { data: result, error } = useSWR(url, fetcher);
if (error) return <div>failed to load</div>
if (!result) return <div>loading...</div>
function filteredTypeHandler(e) {
console.log(e.target.value);
onSelectedType(e.target.value);
}
console.log(selectedPokemonType)
return(
<div className="pokemon-types__sidebar">
<h2>Filter Pokémon by type</h2>
<select
name="pokemon-type"
className="pokemon-types__filter"
onChange={filteredTypeHandler}
>
<option value="All">Filter By Type</option>
{result.results.map((type) => {
return (
<option key={type.name} value={type.name}> {type.name}</option>
)
})}
</select>
</div>
)
}
export default PokemonFilter;
Here is an example to improve, modify, ... I didn't test, it's just a visual example.
I don't know about useSWR sorry, I use axios in my example...
If you want to centralize all your API requests, you can create a useApi hook, on the internet you will find tutorials.
PokemonList.js
import React, { useState, useEffect } from 'react';
import axios from 'axios'; // or swr
import PokemonFilter from './PokemonFilter';
import PokemonCard from './PokemonCard';
export default function PokemonList() {
const [data, setData] = useState([]);
const [filter, setFilter] = useState('');
// Executed every first render
useEffect(() => {
getData();
}, []);
// Executed only when filter changes
useEffect(() => {
getDataByTypes(filter);
}, [filter]);
// Get data
const getData = async () => {
const uri = 'https://xxx';
try {
const response = await axios.get(uri);
setData(response.data...);
} catch (error) {
console.log(error);
}
};
// Get data by types
const getDataByTypes = async (filter) => {
const uri = `https://xxx/type/${filter}...`;
if (filter) {
try {
const response = await axios.get(uri);
setData(response.data...);
} catch (error) {
console.log(error);
}
}
};
return (
<div className="main">
<PokemonFilter filter={filter} setFilter={setFilter} />
<div className="container">
<div className="cards-container">
{data.map((d) => (
<PokemonCard key={d.name} data={d} />
))}
</div>
</div>
</div>
);
}
PokemonCard.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
export default function PokemonCard({ data }) {
const [pokemons, setPokemons] = useState();
useEffect(() => {
getPokemons(data);
}, [data]);
// Get Pokemons
const getPokemons = async (data) => {
const uri = `https://xxx/pokemon/${data.name}/`;
try {
const response = await axios.get(uri);
setPokemons(response.data...);
} catch (error) {
console.log(error);
}
};
return (
<div>
{pokemons && (
<div className="card">
<img src={pokemons.sprites.front_default} alt={pokemons.name} />
<p>{pokemons.name}</p>
<p>{pokemons.abilities[0].ability.name}</p>
<p>{pokemons.types[0].type.name}</p>
</div>
)}
</div>
);
}
PokemonFilter.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
export default function PokemonFilter({ filter, setFilter }) {
const [types, setTypes] = useState([]);
useEffect(() => {
getType();
}, []);
// Get Type
const getType = async () => {
const uri = 'https://xxx/type/';
try {
const response = await axios.get(uri);
setTypes(response.data.results....);
} catch (error) {
console.log(error);
}
};
const handleFilter = (e) => {
setFilter(e.target.value);
};
return (
<select onChange={handleFilter} value={filter}>
<option>Filter by type</option>
{types.map((type) => {
return (
<option key={type.name} value={type.name}>
{type.name}
</option>
);
})}
</select>
);
}

Save and Edit post in reactjs and redux

I've been trying to create a blog like website where user can add new post, save them and edit them later. I'm making this website in reactjs and redux. I've few confusions as to how to edit the post, like how will my website know that the user has clicked on this certain post to edit. To do I've used link from react router with the id at the end of the url but I'm not sure if it's the right way to do. Also, when I open the editor page of an existing post, it should load as it was last saved, i.e both the title input and the textarea should already be loaded with text when a user clicks on an already existing posts from the homepage.
I've created a codesandbox of the website. I'm not sure why all the lines in the switch statements in the reducer file is underlined with red.
this is my home.js file where the snippets will load
import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { onLoad, setEdit } from "./actions/posts";
import { connect } from "react-redux";
class Home extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
//Load all the snippets
onLoad();
}
render() {
const { snippets } = this.props;
return (
<div className="container">
<div className="row pt-5">
<div className="col-12 col-lg-6 offset-lg-3">
<h1 className="text-center">Snippets</h1>
</div>
</div>
<div className="row pt-5">
<div className="col-12 col-lg-6 offset-lg-3">
{snippets.map(snippet => {
return (
<div className="card my-3" key={snippet.snippetData.snippetId}>
<div className="card-header">{snippet.title}</div>
<div className="card-body">{snippet.snippetDescription}</div>
<div className="card-footer">
<div className="row">
<button
// onClick={() => this.handleEdit(snippet)}
className="btn btn-primary mx-3"
>
<Link to={`/editor/:${snippet.snippetData.snippetId}`}>
Edit
</Link>
</button>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
snippets: state.snippets,
snippetData: state.snippetData
});
export default connect(
mapStateToProps,
{ onLoad, setEdit }
)(Home);
editor.js page
import React, { Component } from "react";
import { connect } from "react-redux";
import { savePost, retrievePost } from "./actions/posts";
class Editor extends Component {
state = {
title: "",
enteredText: ""
};
componentDidMount() {
//Load the snippet
retrievePost(); // will it load the snippetId too?
}
handleChange = event => {
const { value } = event.target;
this.setState({
enteredText: value
});
};
// Save Snippet
performSave = snippetData => {
const { enteredText, title } = this.state;
savePost(snippetData.snippetId, enteredText, title); //is it the right way to send the parameters to save the post??
};
render() {
return (
<>
<input
type="text"
id="titletext"
placeholder="Enter title here"
limit-to="64"
className="inptxt"
onChange={title => this.setState({ title })}
/>
<button
className="btn savebtn"
onClick={() => this.handlePost({ ...this.state })}
>
Save Snippet
<i className="fas fa-save" />
</button>
<div
contentEditable={true}
spellCheck="false"
name="enteredText"
placeholder="Enter your text here"
onChange={this.handleChange}
/>
</>
);
}
}
const mapStateToProps = state => ({
snippetData: state.snippetData
});
export default connect(
mapStateToProps,
{ savePost, retrievePost }
)(Editor);
actions.js file
import { SAVE_POST, UPDATE_POST, RETRIEVE_POST, HOME_LOADED } from "./types";
export const savePost = ({
snippetId,
snippetDescription,
snippetTitle
}) => async dispatch => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
let snippetData = { snippetId, snippetDescription, snippetTitle };
try {
if (snippetId == null) {
const res = await axios.post(
"/api/save",
JSON.stringify(snippetData),
config
);
snippetData.snippetId = res.data;
dispatch({
type: SAVE_POST,
payload: snippetData
});
} else {
const res = await axios.post(
"/api/update",
JSON.stringify(snippetData),
config
);
dispatch({
type: UPDATE_POST,
payload: snippetData
});
}
} catch (err) {
console.log(err);
}
};
// Retrieve post
export const retrievePost = snippetId => async dispatch => {
try {
const res = await axios.post(`/api/snippetdata/${id}`);
dispatch({
type: RETRIEVE_POST,
payload: res.data
});
} catch (err) {
console.error(err);
}
};
//Retrieve all the post
export const onLoad = () => async dispatch => {
try {
const res = await axios.post(`/api/mysnippets/`);
dispatch({
type: HOME_LOADED,
payload: res.data
});
} catch (err) {
console.error(err);
}
};
// edit a post
First, I have fixed some problems for you:
https://codesandbox.io/s/amazing-bird-dd2mb
I did not fix the editor page, cuz I give up, it is meaningless to give you a working code while learning nothing.
I suggest you stop playing react now, you do not have enough experience to use a complex framework.
What problem your code has:
Wrongly import a commonJS module
Misuse combineReducers
Misuse html form element
Misuse js switch
Do not understand redux state correctly
Do not understand reducer fully
Do not have basic debuging skills
...
STOP WRITING CODE THAT YOU DO NOT UNDERSTAND
This project is too complex for a beginner.
I suggest you:
Implement a counter in vanilla js
Implement a todo list in vanilla js
RE-implement the counter with pure react, no redux, no react-router
RE-implement the counter with react + redux
RE-implement the counter with react + redux + thunk
RE-implement the counter with react + redux + saga
Repeat 3-6 but a todo list.
Then try to code a blog.

Uncaught (in promise) TypeError: Cannot read property 'fisierUrl' of undefined

I create a react app and i want to fetch data (images urls)from my API.
in Detali .js i wrote this code:
Detalii.js
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import url from "../url";
import Header from "../components/Header";
const Detalii = () => {
const [info, setInfo] = useState({});
const { id } = useParams();
useEffect(() => {
async function getData() {
try {
const res = await fetch(`${url}/detalii/${id}`);
const data = await res.json();
setInfo(data);
} catch (error) {
console.log(error);
}
}
getData();
}, [id]);
//console.log(info);
return (
<div className="bg-detalii">
<Header info={info} />
</div>
);
};
export default Detalii;
in Header conponent i display image like this:
Header.js:
import React from "react";
const Header = ({ info }) => {
console.log(info);
return (
<div className="header">
<img src={info.fisier.fisierUrl} className="img-detalii" alt="poza" />
<p className="text-detalii">{info.nume}</p>
</div>
);
};
export default Header;
in my console info.fisier object is like this:
in Detali.js it shows me the error when it displays image.how to fix it? thanks
look at the src={info.fisier.fisierUrl} especially at info.fisier.fisierUrl.
At the beginning your request is in progress and your info is equal to {}.
So it's {}.fisier.fisierUrl. {}.fisier is undefined. And undefined.fisierUrl throws an error
How to fix:
Instead of src={info.fisier.fisierUrl} try src={info && info.fisier && info.fisier.fisierUrl}
I believe the issue is that you try to render <Header /> before the fetch call has returned and setInfo has been called.
One solution could be to render Header only when info is "truthy". I.e.
return (
<div className="bg-detalii">
{info && (<Header info={info} />)}
</div>
);

Categories

Resources