pass state as props in component child in React - components

I get data from a local server, catch them with axios.get, and save them in my state. It's ok, but when i want to pass it as props in an component child, KABOOM! Doesn't work.
I'm looking for a solution, I think it's lyfecycle problem but i'm not sure.
App.js
import React, { Component } from 'react';
import './style/App.css';
import axios from 'axios'
import Table from './Components/Table'
class App extends Component {
state = {
tabData: [],
}
componentWillMount = () => {
this.getDataFromServer()
}
getDataFromServer = () => {
axios.get("http://localhost:8000")
.then((response) => {
const twentyObj = response.data.splice(-20);
this.setState({
tabData:twentyObj
})
console.log(this.state.tabData)
})
.catch(function (error) {
console.log(error);
})
}
render() {
return (
<div className="App">
<Table stateData={this.state.tabData}/>
</div>
);
}
}
export default App;
Developer Tools Browser say:
TypeError: _this.props is undefined
(for this.props.tabData.map in Table.js)
Table.js
import React from 'react';
import Cell from './Cell'
const Table = (props) => {
return(
<div>
{this.props.tabData.map( item =>
<Cell key={item.index}
time={item.timestamp}
nasdaq={item.stocks.NASDAQ}
cac40={item.stocks.CAC40}/>
)}
</div>
)
}
export default Table;

Table is functional component this has no value there and thats what the error message is telling you.
You should use props.tabData and not this.props.tabData
UPDATE:
Here you are passing it as stateData and not tabData Try props.stateData

Related

NEXT.js Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource

Hi guys I've created fullstack app with NEXT.js, TypeScript, NODE.js and MongoDB. Generally this is decode\encode app with all functionality on Backend side. My backend side is already deployed on heroku. Front-end I still have on a localhost till I solve this problem. When I fetch all of my data from Backend, first I see error mesage, then data from Backend.
Here below error msg:
And here below my code:
import { ListProps } from "./List.props";
import styles from "./List.module.css";
import { P } from '../'
import React, { useEffect, useState } from "react";
import axios from "axios";
export const List = ({ children, className, ...props }: ListProps): JSX.Element => {
const [blogs, setBlogs] = useState<any[]>([]);
useEffect(() => {
const fetchData = async () => {
await fetch(`https://node-test-mongo.herokuapp.com/api/blog`)
.then((response) => {
return response.json();
})
.then((data) => {
setBlogs(data.blogs)
})
};
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [blogs]);
return (
<div
className={styles.ul}
{...props}
>
{blogs && blogs.map((blog, index) => (
<ul key={blog._id}>
<li className={styles.li}>
<P className={styles.title} size='l'>{blog.title}</P>
<P size='l'>description={blog.text} </P>
</li>
</ul>
))}
</div>
)
};
I suppose, that there could be something wrong with my data fetching, but I'm not sure.
Thank you in advance!:)

Trouble with dividing an API into multiple components instead of just one

I'm having trouble for the past few days in this problem.
Explanation of the problem:
I'm using Axios in order to get data inside of state (Pokémon's), But, everything is rendering inside one component (creating an array and list and shows the list) , while I need every Pokémon I get from the API to be inside his own component (so that I can images per Pokémon and etc.)
Does anybody perhaps knows how to do so? If u do, please answer and explain to me (And if it wont be any trouble, modify the code), Thanks in advance, Mikey. (Using react-ts, node.js and axios)
import React, { useState, useEffect } from 'react';
import axios from 'axios';
export default function PokeCont() {
const [pokemons, setPokemons] = useState<any>();
const onClick = () => {
axios.get('https://pokeapi.co/api/v2/pokemon?limit=6').then((response) => {
setPokemons(response.data.results);
});
};
useEffect(() => {
onClick();
}, []);
return (
<div>
{pokemons &&
pokemons.map((pokemon: any) => (
<div key={pokemon.name}>
<p>{pokemon.name}</p>
</div>
))}
</div>
);
}
Here is an example ;)
import { useState, useEffect } from "react";
import axios from "axios";
export default function App() {
return (
<div className="App">
<PokemonContainer />
</div>
);
}
function PokemonContainer() {
const [pokemons, setPokemons] = useState<any[]>([]);
const onClick = () => {
axios.get("https://pokeapi.co/api/v2/pokemon?limit=6").then((response) => {
setPokemons(response.data.results);
});
};
useEffect(() => {
onClick();
}, []);
return (
<div>
{pokemons &&
pokemons.map((pokemon) => (
<PokemonItem key={pokemon.name} info={pokemon} />
))}
</div>
);
}
function PokemonItem({ info }) {
return (
<div>
<h2>{info.name}</h2>
<img src={info.image} width="100" height="100" alt=""></img>
</div>
);
}
Add necessary changes to components like export default and types.
import React, { useState, useEffect } from 'react'
import axios from 'axios'
***Component 1: Pokemon***
Pokemon = props => {
return (
<>
<div key={props.name}>
<p>{props.name}</p>
</div>
</>
)
}
***Component 2: Parent Pokemon which renders your Pokemon as Component ***
export default function PokeClass() {
const [pokemons, setPokemons] = useState()
const onClick = () => {
axios.get("https://pokeapi.co/api/v2/pokemon?limit=6").then((response) => {
setPokemons(response.data.results)
})
}
useEffect(() => {
onClick()
}, []);
return (
<>
{pokemons.map((item => {
return <Pokemon name={item.name} />
}))}
</>
)
}

I am trying to display data from an external API, how can I fix the issue in my code?

This is the error message I am getting
TypeError: undefined is not an object (evaluating 'drinkList.drinks[0]')
How can I fix the error so that I can use the app to fetch data from the external api?
This is my drink.js code:
import React, { useEffect, useState } from "react";
import axios from "axios";
import Drinks from "./Drinks";
function Home() {
const [drinkName, setDrinkName]= useState([]);
const [drinkList, setDrinkList] = useState([]);
const drinksURL = `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${drinkName}`;
const handleChangeDrink= e => {
setDrinkName(e.target.value);
}
const getDrink = () => {
axios
.get(drinksURL)
.then(function (response) {
setDrinkList(response.data);
console.log(drinksURL);
})
.catch(function (error) {
console.warn(error);
});
};
return (
<main className="App">
<section className="drinks-section">
<input
type="text"
placeholder="Name of drink (e.g. margarita)"
onChange={handleChangeDrink}
/>
<button onClick={getDrink}>Get a Drink Recipe</button>
<Drinks drinkList={drinkList} />
</section>
</main>
);
}
export default Home;
This is my Drink.js code:
import React from "react";
function Drinks({ drinkList }) {
if (!drinkList) return <></>;
return (
<section className="drinkCard">
<h1>{drinkList.drinks[0].strDrink}</h1>
</section>
);
}
export default Drinks;
Couple of problems here...
drinkName is initialised as an array but it appears to be expecting a string
drinkList is initialised as an array but the data from the API is an object. You may want to assign the drinks array from the response instead
drinksUrl is never updated
An empty array is still truthy
Some easy fixes
const [drinkName, setDrinkName]= useState(null) // initialise as null
const [drinkList, setDrinkList] = useState([])
// don't include the "s" parameter here
const drinksURL = "https://www.thecocktaildb.com/api/json/v1/1/search.php"
const getDrink = () => {
// pass drinkName as a param
axios.get(drinksURL, {
params: { s: drinkName }
}).then(res => {
// note that we're extracting `drinks`
setDrinkList(res.data.drinks)
}).catch(console.warn)
}
and in Drink.js
function Drinks({ drinkList }) {
// check the array length
return drinkList.length && (
<section className="drinkCard">
<h1>{drinkList[0].strDrink}</h1>
</section>
)
}

Only one element of type cardNumber can be created

I am trying to display my stripe component, but I am getting this error:
IntegrationError: Only one element of type cardNumber can be created.
I don't know why, since I'm only using it once in my entire app
Any ideas?
This is my index
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { loadStripe } from "#stripe/stripe-js";
import { Elements } from "#stripe/react-stripe-js";
import MyComponent from './components/StripeComponent';
const promise = loadStripe("xxx-xxx-xxx");
ReactDOM.render(
<React.StrictMode>
<Elements stripe={promise}>
<MyComponent/>
</Elements>
</React.StrictMode>,
document.getElementById('root')
);
And this is my component
import React from "react";
import {
useElements,
} from "#stripe/react-stripe-js";
const MyComponent: React.FC= (props)=>{
const elements = useElements();
const cardNumberElement = elements?.create('cardNumber', {
placeholder: ''
});
const cardExpiryElement = elements?.create('cardExpiry', {
placeholder: ''
});
const cardCvvElement = elements?.create('cardCvc', {
placeholder: ''
});
cardNumberElement?.mount('#card-number-element')
cardExpiryElement?.mount('#card-expiry-element')
cardCvvElement?.mount('#card-cvv-element')
const handleSubmit = async (ev: any) => {
ev.preventDefault();
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<div id="card-number-element"></div>
<div id="card-expiry-element"></div>
<div id="card-cvv-element"></div>
</form>
);
}
export default MyComponent
Seems it is because you create and mount the card components in the functional component body they are executed on every render of the component, i.e. as an inadvertent side-effect.
Place the creation and mounting logic in an useEffect hook with an empty dependency array so that it is invoked only once when the component mounts.
import React, { useEffect } from "react";
import { useElements } from "#stripe/react-stripe-js";
const MyComponent: React.FC = (props) => {
const elements = useElements();
// Effect hook to run once on component mount
useEffect(() => {
const cardNumberElement = elements?.create("cardNumber", {
placeholder: ""
});
const cardExpiryElement = elements?.create("cardExpiry", {
placeholder: ""
});
const cardCvvElement = elements?.create("cardCvc", {
placeholder: ""
});
cardNumberElement?.mount("#card-number-element");
cardExpiryElement?.mount("#card-expiry-element");
cardCvvElement?.mount("#card-cvv-element");
}, []); // <-- empty dependency array
const handleSubmit = async (ev: any) => {
ev.preventDefault();
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<div id="card-number-element"></div>
<div id="card-expiry-element"></div>
<div id="card-cvv-element"></div>
</form>
);
};
useEffect(() => {
if (elements) {
const cardNumberElement =
elements.getElement("cardNumber") || // check if we already created element
elements.create("cardNumber", defaultInputStyles); // create if dont
cardNumberElement.mount("#numberInput");
}
}, [elements]);
I had the same problem, in my case, I had a reference to CardNumberElement in another section of my code. After removing it, everything worked fine.

Losing currentUser when App component refreshes?

I am currently working on a simple web app using React, Node.js, passport-google-oauth20.
For some reason, whenever the application re-mounts, I lose the currentUser state. It's as if req.user is just lost.
The way it works is I first fetch the current user when the application mounts and set this.state.currentUser to the results. The issue is when the page refreshes. The component re-mounts and I lose the user. I tried logging the user and receive null.
Hopefully I explained this well enough... here is the code:
App component:
import React from 'react';
import List from './List';
import ListForm from './ListForm';
import * as helpers from '../helpers';
class App extends React.Component{
state = {
currentUser: '',
}
componentDidMount() {
helpers.fetchUser()
.then(data => {
this.setState({
currentUser: data
});
});
}
onSubmit = (id, item) => {
helpers.addItem(id, item);
}
render() {
return (
<div className="container">
<List
currentUser={this.state.currentUser}
onSubmit={this.onSubmit}
/>
</div>
);
}
};
export default App;
Helpers:
import axios from 'axios';
export const fetchUser = async () => {
const resp = await axios.get('/api/current_user');
return resp.data;
}
export const addItem = (id, newItem) => {
axios.post("/api/" + id + "/addItem", newItem);
}

Resources