Undefined Props in React - javascript

I have the following component in react
import React, { Component } from 'react';
import axios from 'axios'
import Post from './Post'
import Navbar from '../Navbar'
class SinglePost extends Component {
constructor(props) {
super(props);
this.state = {
post: {}
}
}
componentDidMount() {
const { post_id } = this.props.match.params
axios.get(`http://127.0.0.1:8000/posts/${post_id}`)
.then(res => {
this.setState({ post: res.data })
console.log(res.data)
console.log(this.state)
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<Navbar />
<div style={{height: '95px'}}></div>
<Post key={this.state.post.id} post={this.state.post} />
</div>
)
}
}
export default SinglePost;
The correct response is recieved from the backend and set to state properly. However the data passed to the Post component shows up as undefined.
Here is teh post component:
import React from 'react'
import Comment from './Comment'
import CommentForm from './CommentForm'
const placeholder_url = 'https://image.shutterstock.com/image-vector/ui-image-placeholder-wireframes-apps-260nw-1037719204.jpg'
const placeholder = 'data:image/png;base64,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'
function Post(props) {
console.log(props) //Shows up as an empty object
return (
<div className="uk-background-muted uk-margin-top uk-container">
<div>
<div className="uk-background-default">
<img src={props.post.user.pp || placeholder} width="50" height="50" alt={props.post.user.username} />
<a href={`/users/${props.post.user.id}`}>{props.post.user.username}</a>
</div>
<img className="uk-align-center" src={props.post.image || placeholder_url} alt="placeholder" />
<ul>
<li>Likes: {props.post.post_liked.length}</li>
<li>Dislikes: {props.post.post_disliked.length}</li>
<li>Comments: {props.post.comment_post.length}</li>
</ul>
<p className="uk-text-large">{props.post.text}</p>
{props.post.comment_post.map(comment => (<Comment key={comment.id} comment={comment} />))}
<div>
<CommentForm key={props.post.id} post={props.post} />
</div>
</div>
</div>
)
}
export default Post
This is the error I get: TypeError: Cannot read property 'pp' of undefined

State-setting is asynchronous, so whenever you want to act upon data from state, you should include a manual check against undefined values.
Try something like this:
class SinglePost extends Component {
constructor(props) {
super(props);
this.state = {
post: null // null initial value is easier to check than an empty object
}
}
componentDidMount() {
const { post_id } = this.props.match.params
axios.get(`http://127.0.0.1:8000/posts/${post_id}`)
.then(res => {
this.setState({ post: res.data })
console.log(res.data)
console.log(this.state)
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<Navbar />
<div style={{height: '95px'}}></div>
{this.state.post &&
<Post key={this.state.post.id} post={this.state.post} />
}
</div>
)
}
}

The error happens in the first render when post = {} and the Post component is trying to get props.post.user.pp.
To solve the problem, in the SinglePost component, you could initialize post to be null instead of {} and in the Post component, handle the post === null case:
function Post(props) {
if(!props.post) {
return null;
// return <span>Loading</span>;
}
return (
<div className="uk-background-muted uk-margin-top uk-container">
...

Related

Passing the result of a component to render returns an undefined?

I am trying to write a wrapper component around an API call to render "loading" if the api hasnt updated. Im very new to react, but I can t seem to figure out why the state isnt being passed to the ApiResp component:
Here is the console.log of the state changes..... why is the final apiResp in console.log undefined?
App.js
class App extends React.Component {
async componentDidMount() {
let xx = await axios.get(apiUrl)
console.log(`componentDidMount`, xx)
this.setState({ loading: false, body: xx });
}
render() {
console.log(`rendering ComponentLoading`, this.state)
const DisplayComponent = ComponentLoading(ApiResp)
return (
<div className="App">
<header className="App-header">
<img src={face} /*className="App-logo"*/ alt="face-img" />
</header>
<br></br>
<div>
<DisplayComponent isLoading={AppState.loading} body={AppState.body} />
</div>
</div>
);
}
}
export default App;
ComponentLoading:
import React from 'react';
function ComponentLoading(Component) {
return function WihLoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return (
<p style={{ textAlign: 'center', fontSize: '30px' }}>
Loading
</p>
);
};
}
export default ComponentLoading;
apiResp.js
import React from 'react';
const ApiResp = (data) => {
console.log(`apiResp:`, data)
if (!data || data.statusCode !== 200) {
return <p>Err: {JSON.stringify(data)}</p>;
}
else
return (
<div>
<h3>obj:</h3>
{JSON.stringify(data)}
</div>
);
};
export default ApiResp;
ComponentLoading is a Higher Order Component. const DisplayComponent = ComponentLoading(ApiResp) is decorating the ApiResp component:
const ApiResp = (data) => {
console.log(`apiResp:`, data)
if (!data || data.statusCode !== 200) {
return <p>Err: {JSON.stringify(data)}</p>;
}
else
return (
<div>
<h3>obj:</h3>
{JSON.stringify(data)}
</div>
);
};
and returning a component you've called DisplayComponent.
As a component ApiResp is consuming a props object called data and only accesses a statusCode prop.
DisplayComponent is passed two props:
<DisplayComponent isLoading={AppState.loading} body={AppState.body} />
AppState isn't defined in the parent component but it seems this.state has the values you want passed to DisplayComponent.
Solution
Access and pass the correct object to props.
<DisplayComponent
isLoading={this.state.loading}
body={this.state.body}
/>
I suggest also moving the const DisplayComponent = ComponentLoading(ApiResp) declaration out of the render method, and also outside the App component.
const DisplayComponent = ComponentLoading(ApiResp);
class App extends React.Component {
state = {
loading: true,
body: null,
};
async componentDidMount() {
let xx = await axios.get(apiUrl)
console.log(`componentDidMount`, xx)
this.setState({ loading: false, body: xx });
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={face} /*className="App-logo"*/ alt="face-img" />
</header>
<br></br>
<div>
<DisplayComponent
isLoading={this.state.loading}
body={this.state.body}
/>
</div>
</div>
);
}
}

Understanding async in React components

I'm using axios to return the details of a Pokemon:
class PokeDetails extends React.Component{
constructor(props){
super(props);
this.state = { pokemon: null }
}
componentDidMount(){
axios.get('https://pokeapi.co/api/v2/pokemon/1')
.then(res => {
this.setState({
pokemon: res.data
});
}).catch((err) => { console.log('Axios Poke Details error: ', err) });
}
render(){
const {pokemon} = this.state;
const pokeCard = pokemon ? (
<div className="poke-details">
<img src={pokemon.sprites.front_default} alt={`${pokemon.name} front`}/>
<h3 className="card-title">{pokemon.name}</h3>
</div>
) : (
<div className="center">Loading Pokemon...</div>)
return(
<div className="container">
{pokeCard}
</div>
)
}
}
export default PokeDetails
I want to display the pokemon types, which is an array that has a length of 1 or 2 depending on the pokemon. So I thought:
render(){
const {pokemon} = this.state
const listTypes = pokemon.types.map((type) => { <li>{type.name}</li> });
}
...and render listTypes in a ul in const pokeCard. When I do this I get an error saying pokemon is null. Shouldn't this not happen because of the ternary operator rendering the pokeCard?
Using pokemon before its detail get fetched from service, try like given:
const listTypes = pokemon && pokemon.types.map((type) => { <li>{type.name}</li> });
Problem is that componentDidMount is called after the initial render. So on the initial render, pokemon is null. That is why accessing pokemon.types fails.
You need to access pokemon.types only when pokemon is not null. Just move the code where you .map() over the pokemon.types inside the ternary operator.
const pokeCard = pokemon ? (
<div className="poke-details">
<img src={pokemon.sprites.front_default} alt={`${pokemon.name} front`} />
<h3 className="card-title">{pokemon.name}</h3>
<ul>
{pokemon.types.map(({ type }) => (
<li key={type.name}>{type.name}</li>
))}
</ul>
</div>
) : (
<div className="center">Loading Pokemon...</div>
);
Demo:
class PokeDetails extends React.Component {
constructor(props) {
super(props);
this.state = { pokemon: null };
}
componentDidMount() {
axios
.get("https://pokeapi.co/api/v2/pokemon/1")
.then((res) => {
this.setState({
pokemon: res.data
});
})
.catch((err) => {
console.log("Axios Poke Details error: ", err);
});
}
render() {
const { pokemon } = this.state;
const pokeCard = pokemon ? (
<div className="poke-details">
<img
src={pokemon.sprites.front_default}
alt={`${pokemon.name} front`}
/>
<h3 className="card-title">{pokemon.name}</h3>
<ul>
{pokemon.types.map(({ type }) => (
<li key={type.name}>{type.name}</li>
))}
</ul>
</div>
) : (
<div className="center">Loading Pokemon...</div>
);
return <div className="container">{pokeCard}</div>;
}
}
ReactDOM.render(<PokeDetails />,document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.20.0/axios.min.js"></script>
<div id="root"></div>
Rome data is better kept in cache, in case it gets shared between componenets in different levels.
I reproduced your code:
import React from 'react';
import useSWR from 'swr';
const fetcher = async (...args) => {
const res = await fetch(...args);
return res.json();
};
function PokeDetails() {
const { data, error } = useSWR('https://pokeapi.co/api/v2/pokemon/1', fetcher);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return (
<div>
{data ? (
data.map((pokemon) => {
return (
<div className='poke-details'>
<img
src={pokemon.sprites.front_default}
alt={`${pokemon.name} front`}
/>
<h3 className='card-title'>{pokemon.name}</h3>
</div>
);
})
) : (
<div>Some loading content</div>
)}
</div>
);
}
export default PokeDetails;
you can check this article to get a clear idea.

How can i pass props through methods inside components?

i have a react component named "List" that renders smaller components "Post" using a button through method "Addpost()" that takes 2 props from the input form. I have saved the input in 2 varables but i don't know how to pass these props to the Addpost() method inside the return of List's render().
//=========== List component ==============
class List extends React.Component{
renderPost(title,content){
return(
<Post titolo={title} contenuto={content}/>
);
}
renderPost just render the Post component in a in the HTML
addPost(title,content){
title = document.getElementById("inputTitle").value;
content = document.getElementById("inputContent").value;
console.log(title, content)
this.renderPost(title,content);
}
addPost should take the input value and use renderPost to render the Post component with that title and content
render(){
return(
<div>
{this.renderPost("testTitle","testContent")}
<form>
Title:<br></br>
<input type="text" id="inputTitle"/><br></br>
Content:<br></br>
<input type="text" id="inputContent"/>
</form><br></br>
<button className="square"
how can i make this work? title and content are not defined
onClick={() =>
this.addPost(title,content)
Add Post!
</button>
</div>
);
}
}
//=========== Post component ==============
class Post extends React.Component {
render() {
return (
<li className="w3-padding-16">
<img src="/w3images/workshop.jpg" alt="Imagedf" className="w3-left w3-margin-right" />`enter code here`
<span className="w3-large">
{this.props.titolo}
</span><br></br>
<span>{this.props.contenuto}</span>
</li>
);
}
}
Basically, whenever you're dealing with forms and inputs, you would use refs.
App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import PostList from './components/PostList'
import AddPostForm from './components/AddPostForm'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
posts: [] //state is handled here
}
this.addPost = this.addPost.bind(this)
}
addPost(title, content) {
let newPost = { title, content }
this.setState(({ posts }) => { return { posts: [...posts, newPost] } } )
}
render() {
const { posts } = this.state
return (
<div>
<AddPostForm onNewPost={this.addPost} /> //we pass addPost to the component
<br />
<PostList posts={posts} />
</div>
);
}
}
export default App;
Post.js
import React from 'react';
function Post({titolo, contenuto}) {
return (
<li className="w3-padding-16">
<img src="/w3images/workshop.jpg" alt="Imagedf" className="w3-left w3-margin-right" />`enter code here`
<span className="w3-large">
{titolo}
</span><br></br>
<span>{contenuto}</span>
</li>
);
}
export default Post
AddPostForm.js
import React from 'react';
const addPostForm = ({onNewPost = f => f}) => { //onNewPost method is passed by props from the parent
let _titleInput, _contentInput //these are our refs, see the docs for more information
const submit = (e) => {
e.preventDefault()
onNewPost(_titleInput.value, _contentInput.value) //here we call the addPost function that was passed to the component
_titleInput.value = '' //empty the inputs
_contentInput.value = ''
_titleInput.focus() //set focus
}
return (
<form onSubmit={submit}>
Title:<br></br>
<input type="text" ref={title => _titleInput = title} /><br></br>{/* Note the ref attribute */}
Content:<br></br>
<input type="text" ref={content => _contentInput = content} />
<button className="square">Add a new post</button>
</form>
)
}
export default addPostForm
PostList.js
import React from 'react';
import Post from './Post';
const PostList = ({ posts=[] }) => {
return (
<div className="post-list">
{
posts.map((post, index) =>
<Post key={index} titolo={post.title} contenuto={post.content} />
)
}
</div>
)
}
export default PostList
And the result:
edit
renderPost just render the Post component in a in the HTML
state = { inputTitle: '', inputContent: '' }
addPost(title,content){
title = document.getElementById("inputTitle").value;
content = document.getElementById("inputContent").value;
console.log(title, content)
this.renderPost(title,content);
}
addPost should take the input value and use renderPost to render the Post
component with that title and content
render(){
return(
<div>
{this.renderPost("testTitle","testContent")}
<form>
Title:<br></br>
<input type="text" value={this.inputTitle} onChnage={event => setState({ inputTitle: event.target.value }) }><br></br>
Content:<br></br>
<input type="text" value={this.inputContent} onChnage={event => setState({ inputContent: event.target.value }) } />
</form><br></br>
<button className="square"
on click function
onClick={() =>
this.addPost(this.inputTitle,this.inputContent)
Add Post!
</button>
</div>
);
}
}

Passing more than one props to one component

How can I pass more than one props to one component?
For example, I want to render a DIV that has various elements but not all the elements are in the same component.
So here I'm passing the whole component into another component, the problem with this is that ContentSkuInfo component is mapping throw states so all the data is loading in the same place, I need to load de data but ones in each DIV.
I need this:
<div>
<strong>Data 01</strong>
</div>
<div>
<strong>Data 02</strong>
</div>
<div>
<strong>Data 03</strong>
</div>
But I'm having this:
<div>
<strong>Data 01</strong>
<strong>Data 02</strong>
<strong>Data 03</strong>
</div>
This are my components Seccion_uno_contenido.js
import React from 'react';
import ContentSkuInfo from './CallDataStorage';
const ContenidoUno = (props) => {
return (
<div className="contentBox outerBox-first" >
<a href={props.link}>
<img src={props.imagen} alt="bloque 01" className="img-wrap" />
</a>
<h3>{props.categoria}</h3>
<img src={props.icono} className="iconic" alt="producto" />
<span>{props.descripcion}</span>
<ContentSkuInfo />
<small>Antes: ${props.antes}</small>
<div className="containerBotonRow">
¡Lo quiero!</button>
</div>
</div>
);
}
export default ContenidoUno;
CallDataStorage.js
import React from 'react';
import axios from 'axios';
var productsIds = ['3552357', '2635968BC', '3181464', '3593754'];
var productsIdsJoin = productsIds.join('-');
const getProductDetailAPI = (productsIds, storeId) => ({
method: 'GET',
baseURL:`SORRY CAN'T SHOW THIS`,
auth: {
username: 'XXXXXXX',
password: 'XXXXXXX',
},
headers: {
'Content-Type': 'application/json',
},
data: {},
});
const ContentSkuInfo = (props) => {
return (
<strong>$ {props.prodsNormal}</strong>
);
}
class DataStorage extends React.Component {
constructor(props) {
super(props);
this.state = { products: [] };
};
getWebServiceResponse = (currentList, storeId) => (
axios(getProductDetailAPI(currentList, storeId))
.then(response => response.data)
.then(newData => {
this.setState({ products: newData.productDetailsJson })
})
.catch(e => e)
);
componentDidMount() {
this.getWebServiceResponse(productsIdsJoin, 96);
};
render() {
return (
<samp>
{this.state.products.map(skuData =>
<ContentSkuInfo
prodsName={skuData.name}
prodsId={skuData.productId}
prodsStatus={skuData.status}
prodsPublished={skuData.published}
prodsNormal={skuData.NORMAL}
prodsCMR={skuData.CMR}
prodsAhorro={skuData.savings}
prodsCombo={skuData.combo}
prodsStock={skuData.stockLevel}
/>
)
}
</samp>
)
}
}
export default DataStorage;
Just change the definition of ContentSkuInfo in CallDataStorage.js to
const ContentSkuInfo = (props) => (
<div>
<strong>$ {props.prodsNormal}</strong>
</div>
)
You are not passing any props to ContentSkuInfo component in your code. To access something via props inContentSkuInfo you need to pass some properties to ContentSkuInfo.
For eg
When you are calling ContentSkuInfo In your ContenidoUno component you need to send something like below
<ContentSkuInfo prodsNormal=“testing” prodsNormal2=“test2”/>
And in ContentSkuInfo component you can get it like remove $ from expression
Without return
const ContentSkuInfo = (props) => (
<div>
<div>
<strong>{props.prodsNormal}</strong>
</div>
<div>
<strong>{props.prodsNormal2}</strong>
</div>
</div>
)
With return
const ContentSkuInfo = (props) => {
return (
<div>
<div>
<strong>{props.prodsNormal}</strong>
</div>
<div>
<strong>{props.prodsNormal2}</strong>
</div>
</div>
)}

Console won't work / state doesnt update

i'm working on my code. First of all my App.js:
import React, { Component } from 'react';
// import logo from './logo.svg';
import './App.css';
import Flat from './components/flat.js'
class App extends Component {
constructor(props) {
super(props);
this.state = {
flats: []
};
}
componentDudMount() {
const url = "https://raw.githubusercontent.com/lewagon/flats-boilerplate/master/flats.json";
fetch(url)
.then(response => response.json())
.then((data) => {
this.setState({ //console.log(data);
flats: data
});
})
}
render() {
return (
<div className="app">
<div className="main">
<div className="search">
</div>
<div className="flats">
{this.state.flats.map((flat) => {
return <Flat flat={flat} />
})}
</div>
</div>
<div className="map">
</div>
</div>
);
}
}
export default App;
Then my flat.js
import React from "react";
import "./flat.css";
class Flat extends React.Component {
render() {
const title = this.props.flat.price
+ this.props.flat.priceCurrency + " - " + this.props.flat.name;
const style = {
backgroundImage: `url('${this.props.flat.imageUrl}')`
};
return (
<div className="flat">
<div className="flat-picture" style={style}></div>
<div className="flat-title">
{title}
</div>
</div>
);
}
}
export default Flat
First of all on line that should update state i wrote a console.log that should have give me a log in console. It doesnt, my console is blank. All i did was set up my react by create-react-app.
Second thing, my code doesnt fetch a json. I'm sitting on it for hours and can't see whats wrong. Thanks for help in advance.
Video that i'm following: https://www.youtube.com/watch?v=_ZTT9kw3PIE&t=3665s&index=4&list=PL3IsCNRIBp-jOC5vjf1ITYDVgwngDqtzz
You have a type in lifecyle hook componentDidMount
Secondly, a console.log() statement is not valid inside an object, so
this.setState({ //console.log(data);
flats: data
});
is invalid,
You can have a console.log() statement before setState like
fetch(url)
.then(response => response.json())
.then((data) => {
console.log(data);
this.setState({
flats: data
});
})
or use functional setState(although it isn't really useful here)
fetch(url)
.then(response => response.json())
.then((data) => {
this.setState(() => {
console.log(data);
return {flats: data}
});
})
it need to be componentDidMount() not componentDudMount() , one more thing
change your render methode to be like this , with this way you will only render when the state is updated
render() {
if(!this.state.flats){
return(<div>Loading ......</div>
}
return (
<div className="app">
<div className="main">
<div className="search">
</div>
<div className="flats">
{this.state.flats.map((flat) => {
return <Flat flat={flat} />
})}
</div>
</div>
<div className="map">
</div>
</div>
);
}

Categories

Resources