React - trying to save fetched data in a variable but the variable returns empty - node.js

I fetched json data with async await and i wanted to save the fetched data in a variable in order to be able to use it with a map in my component,
the data comes in properly inside the function - i checked with an alert , and also in the variable inside the function it does display all the data , but somehow the variable outside the function returns empty .
here is some code:
both alerts in the following code return the right data.
export let fetchPosts = [];
export async function FetchPosts() {
await axios.get('https://jsonplaceholder.typicode.com/posts').then(
res => {
alert(JSON.stringify(res.data))
fetchPosts = JSON.stringify(res.data);
alert(fetchPosts)
}
).catch(err => {
alert('err');
})
}
import { fetchPosts } from '../services/post';
import { FetchPosts } from '../services/post';
export default function Posts() {
function clickme() {
FetchPosts()
}
return (<>
<button onClick={clickme}>Click me</button>
{fetchPosts.map((post, index) => (
<div key={post.id} className="card" style={{ 'width': '16rem', 'display': 'inline-block', 'margin': '5px' }}>
<div className="card-body">
<h6 className="title">{post.title}</h6>
<p className="card-text">{post.body}</p>
</div>
</div>
))}
</>)
}

State is the issue
React doesn't automatically reload on your singleton fetchPosts.
Instead, try...
export function FetchPosts() {
return axios.get('https://jsonplaceholder.typicode.com/posts');
}
then
import { useState } from 'react';
import { FetchPosts } from '../services/post';
export default function Posts() {
const [posts, setPosts] = useState([]);
function clickme() {
FetchPosts().then(res => {
setPosts(res.data);
});
}
return (<>
<button onClick={clickme}>Click me</button>
{posts.map((post, index) => (
<div key={post.id} className="card" style={{ width: '16rem', display: 'inline-block', margin: '5px' }}>
<div className="card-body">
<h6 className="title">{post.title}</h6>
<p className="card-text">{post.body}</p>
</div>
</div>
))}
</>)
}
https://codesandbox.io/s/jolly-almeida-q4331?fontsize=14&hidenavigation=1&theme=dark
If you want global state, that's another topic you should dive into entirely but you can do it with a singleton, you just need to incorporate it with hooks and an event emitter. I have a bit of a hacked version of this here https://codesandbox.io/s/react-typescript-playground-forked-h8rpu but you should probably stick to redux or mobx or AppContext which is more of a popular pattern.

Related

How to get form data onSubmission in React-remix by using useFetcher Hook using fetcher.submit()

I have a simple component with an input field and a submit button. I just want to get my data after i fill the input field and submit the form. by using useFetcher hook and fetcher.submit().
import { useEffect } from 'react';
import { useFetcher } from '#remix-run/react'
import { ActionFunction } from '#remix-run/node';
function fetchHook() {
const fetch = useFetcher();
useEffect(() => {
console.log("useEffect");
}, []);
return (
<div>
<h1> Use Fetcher Hook</h1>
<fetch.Form action='/fetcher' method='post'>
<div>
<input type="text" name="name" id="" />
<button type='submit' > Submit</button>
</div>
</fetch.Form>
</div>
)
}
export default fetchHook;
export const action: ActionFunction = async ({ request }) => {
}
What changes should i make to get my desired result. I am new to react-remix.

Nextjs: Cant render a component while using map over a array of objects. Objects are not valid as a React child

I dont know why when i want to render a component inside of a map function, basiclly i have a List component, and when i fetch data from an API with the email, etc.. from users i want that component to render that info. But i get the following error:
Unhandled Runtime Error
Error: Objects are not valid as a React child (found: object with keys {email, phone, nick}). If you meant to render a collection of children, use an array instead.
My List component looks like this:
import React from 'react'
export default function List(email, nick, phone) {
return (
<div align="center">
<hr />
<strong>Email: </strong>
<p>{email}</p>
<strong>Nick: </strong>
<p>{nick}</p>
<strong>Phone: </strong>
<p>{phone}</p>
</div>
)
}
And my List user page looks like this:
import React from 'react'
import Nav from '../../components/Nav/Nav'
import { useEffect, useState } from 'react';
import List from '../../components/User/List';
export default function index() {
const [users, setUsers] = useState([])
const fetchUsers = async () => {
const response = await fetch("http://localhost:3001/api/internal/users");
const data = await response.json();
console.log(data["data"])
setUsers(data["data"])
}
useEffect(() => {
fetchUsers()
}, [])
return (
<div>
<Nav />
{users.map(user => (
<List
email={user.attributes.email}
phone={user.attributes.phone}
nick={user.attributes.nick}
/>
))}
</div>
)
}
UPDATE 21 ABR
For some reason when i do this :
export default function List(email, phone, nick) {
return (
<div align="center">
<hr />
<strong>Email: </strong>
<p>{email.email}</p>
<strong>Nick: </strong>
<p>{email.phone}</p>
<strong>Phone: </strong>
<p>{email.nick}</p>
</div>
)
}
It works... Someone knows what it can be?
You are passing the props in a wrong way. Either use it as a single object in props or have all the props it inside {} using destructuring method.
export default function List({email, phone, nick}) {}
OR
export default function List(props) {
return (
<div align="center">
<hr />
<strong>Email: </strong>
<p>{props.email}</p>
<strong>Nick: </strong>
<p>{props.phone}</p>
<strong>Phone: </strong>
<p>{props.nick}</p>
</div>
)
}

React, update component after async function set

I want to add data and see in below, and also when I start app, I want see added records. But I can see it, when I'm try to writing something in the fields.
The thing is, the function that updates the static list is asynchronous. This function retrieves data from the database, but before assigning it to a variable, the page has been rendered. There is some way to wait for this variable or update information other way than when you try to type it in the fields. This is before the form is approved.
[![enter image description here][1]][1]
class AddAdvertisment extends React.Component <any, any> {
private advertisment;
constructor(props, state:IAdvertisment){
super(props);
this.onButtonClick = this.onButtonClick.bind(this);
this.state = state;
this.advertisment = new Advertisement(props);
}
onButtonClick(){
this.advertisment.add(this.getAmount(), this.state.name, this.state.description, this.state.date);
this.setState(state => ({ showRecords: true }));
}
updateName(evt){
this.setState(state => ({ name: evt.target.value }));
}
....
render() {
return (<React.Fragment>
<div className={styles.form}>
<section className={styles.section}>
<input id="name" onChange={this.updateName.bind(this)} ></input>
<input id="description" onChange={this.updateDescription.bind(this)} ></input>
<input type="date" id="date" onChange={this.updateDate.bind(this)} ></input>
<button className={styles.action_button} onClick={this.onButtonClick.bind(this)}>Add</button>
</section>
</div>
{<ShowAdvertismentList/>}
</React.Fragment>
);
}
class ShowAdvertismentList extends React.Component <any, any>{
render(){
let listItems;
let array = Advertisement.ad
if(array !== undefined){
listItems = array.map((item) =>
<React.Fragment>
<div className={styles.record}>
<p key={item.id+"a"} >Advertisment name is: {item.name}</p>
<p key={item.id+"b"} >Description: {item.description}</p>
<p key={item.id+"c"} >Date: {item.date}</p>
</div>
</React.Fragment>
);
}
return <div className={styles.adv_show}>{listItems}</div>;
class Advertisement extends React.Component {
public static ad:[IAdvertisment];
constructor(props){
super(props);
if(!Advertisement.ad){
this.select_from_db();
}
}
....
select_from_db = async () => {
const res = await fetch('http://localhost:8000/select');
const odp = await res.json();
if(odp !== "brak danych")
odp.forEach(element => {
if(Advertisement.ad){
Advertisement.ad.push(element);
}
else{
Advertisement.ad = [element];
I try to create function and child like:
function Select_from_db(){
const[items, setItems] = useState();
useEffect(() => {
fetch('http://localhost:8000/select')
.then(res => res.json())
.then(data => setItems(data));
}, []);
return <div className={styles.adv_show}>{items && <Child items={items}/>}
</div>;
}
function Child({items}){
return(
<>
{items.map(item => ( ...
))}
</>
And is working good in first moment, but if I want add item to db I must refresh page to see it on a list below.
I use is instead ShowAdvertismentList in render function. Elements be added to db but not showing below. In next click is this same, until refresh page.
And in my opinio better use a list, becouse I musn't want to conect to database every time to download all records.
[1]: https://i.stack.imgur.com/IYSNU.gif
I now recipe. I must change state on componentDidMount in AddAdvertisment class.
async componentDidMount(){
let z = await setTimeout(() => {
this.setState(state => ({ loaded: true}));
}, 1000);
}
render() {
return (<React.Fragment >
(...)
{this.state.loaded ? <ShowAdvertismentList /> : <Loading/>}
</React.Fragment>
);
}

How to print JSON data from console to webpage in React component

I have an array like this in React data file and I'm using the .map() method to load JSON data in component ProjectItem.js.
When I type {console.log("title" + projects[0].title)} and log data Projecttitle1 appears on console. How should I take the data, render that data on my web-app itself in functional component? (Projecttitle1 to show on the web-app)
Data.json
{
"projects": [
{
"title": "Projecttitle1",
"category": "frontend development",
"description": "",
"desktop": [],
"mobile": []
}
]
}
ProjectItem.js
import React from 'react';
import './ProjectItem.scss';
import useWindowWidth from '../../Hooks/useWindowWidth.js';
import { projects } from '../../data'
import desktopImage from '../../Assets/Images/Projects/Desktop/123.jpg';
import mobileImage from '../../Assets/Images/Projects/Mobile/123_square.jpg'
const ProjectItem = ({ viewProject }) => {
const imageUrl = useWindowWidth() >= 650 ? desktopImage : mobileImage;
const { windowWidth } = useWindowWidth();
return(
<div className="projectItem" style={{ backgroundImage: `url(${ imageUrl })`}}>
{windowWidth >= 650 &&(
<>
<div className="title">
{projects.map((data, key)=>{
console.log(key);
return(
<div key={key}>
{data.title}
</div>
);
})}
</div>
<div className="viewProject">{viewProject}</div>
</>
)}
</div>
);
};
export default ProjectItem
Console:
I've tried some attemps to import json file and then deconstruct from parsed json. Now when I run npm the data still isn't printing on web-app. Would there be possible solution to this?
attempt1:
import data from '../../data'
const { projects } =() => JSON.parse(data)
attempt2:
import data from '../../data'
const {projects} =() => JSON.parse(JSON.stringify(data))
You are trying to deconstruct from json file which is basically a string representation of your object.
you need to import it, and then deconstruct from a parsed json
solution for this would be:
import data from '../../data'
const { windowWidth } = useWindowWidth();
const { projects } = JSON.parse(data)
return(
<div className="projectItem" style={{ backgroundImage: `url(${ imageUrl })`}}>
{windowWidth >= 650 &&(
<>
<div className="title">
{projects.map((data, key)=>{
console.log(key);
return(
<div key={key}>
{data.title}
</div>
);
})}
</div>
<div className="viewProject">{viewProject}</div>
</>
)}
</div>
);

"Expected `onClick` listener to be a function, instead got a value of `string` type (ReactJS/MaterialUI)

I create a login button that onClick logs the user in and then the generated information is stored in the local storage, but I keep getting an "Expected onClick listener to be a function, instead got a value of string type. I am using reactJS to do so.
// Global Navigation Bar
import { connect } from "react-redux";
import React, { Component } from "react";
import cognitoUtils from "lib/cognitoUtils";
import "assets/css/Base.css";
import Avatar from "#material-ui/core/Avatar";
import Tooltip from "#material-ui/core/Tooltip";
import AccountCircleOutlinedIcon from "#material-ui/icons/AccountCircleOutlined";
import AccountCircleIcon from "#material-ui/icons/AccountCircle";
const mapStateToProps = state => {
return { session: state.session };
};
class SignInOut extends Component {
onSignOut = e => {
e.preventDefault();
cognitoUtils.signOutCognitoSession();
};
state = {
on: true
};
toggle = () => {
this.setState({
on: !this.state.on
});
};
render() {
return (
<div>
<button className="profile_button" onClick={this.toggle}>
{this.state.on && (
<div>
{this.props.session.isLoggedIn ? (
<div>
<a
className="Home-link"
href="/home"
onClick={this.onSignOut}
>
<Tooltip title="Profile">
<Avatar className="profile_icon">
<AccountCircleIcon className="profile_icon_in" />
</Avatar>
</Tooltip>
</a>
</div>
) : (
<div>
<a
className="Home-link"
href={cognitoUtils.getCognitoSignInUri()}
onClick="/home"
>
<Tooltip title="Profile">
<Avatar className="profile_icon">
<AccountCircleOutlinedIcon className="profile_icon" />
</Avatar>
</Tooltip>
</a>
</div>
)}
</div>
)}
</button>
</div>
);
}
}
export default connect(mapStateToProps)(SignInOut);
Because you are passing String type to onClick
onClick="/home"
You need to pass a function as stated in the error. something like you did before
onClick={this.onSignOut}

Resources