In React.js array value is not passing properly via props? - ecmascript-6

I have a react app that has two components one Customer and another called Tags. The Customer sends its state's tags value to Tags. As following:
Customer.jsx
import React from "react";
import Tags from "./Tags.jsx";
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.state = {customer:''};
}
componentDidMount(){
const url = `http://localhost:3000/api/customers/${this.props.params.id}`
fetch(url)
.then(res=>res.json())
.then(data=>{
console.log(data);
this.setState({
customer: data
});
})
.catch(error=>{
console.log(error)
});
}
render() {
return (
<div>
Company Name :{this.state.customer.companyName}
Customer Name :{this.state.customer.name}
Tags: <Tags tags={this.state.customer.tags} />
</div>
);
}
}
Tags.jsx
import React from "react";
export default class Tags extends React.Component {
constructor(props) {
super(props);
}
render() {
let tags = this.props.tags.map(tag=>{
return (<span>tag</span>);
});
return (
<div>
{tags}
</div>
);
}
}
When I run the code I get, "TypeError: Cannot read property 'map' of undefined(…)". If I replace below from Tags.jsx
let tags = this.props.tags.map(tag=>{
return (<span>tag</span>);
});
with
console.log(this.props.tags);
The output is an array.
What is happening? I really do not understand. What can I do?

In the constructor of Customer you are defining the state of a customer as a string, not an object. You should change it to reflect the actual customer properties, ie:
this.state = {customer: {name: '', tags: []}};

It's undefined, because of you're making an API call and the data isn't returned yet.
In your Customer component you can check the existance of this.state.customer.tags and if exist - then render the tags.
Somethling like that:
{ this.state.customer.tags ? <Tags tags={this.state.customer.tags} /> : null }

Related

Cannot read property 'map' of undefined in React + Phoenix framework

I'm new to React. I have provided Postgresql API and I want to add those data in Material UI Table.
I've made some mistakes and I'm unable to figure to out.
I'm using API calls for the first time using Axios. So please guide me to solve this issue.
I'm using React.js for frontend work, Phoenix framework for backend, and PostgreSQL database.
The below component is used to handle API request using Axios
import axios from "axios"
import MedicineCard from './MedicineCard'
class Medicines extends React.Component {
constructor() {
super();
this.state = { medicines: [] };
}
componentWillMount() {
axios.get('http://localhost:4000/medicines')
.then(response => {
this.setState({ medicines: response.data.medicines });
})
.catch(error => {
console.log(error);
});
}
render() {
const posts = this.state.medicines.map((medicine, index) =>
<MedicineCard
key = { index }
medid = {medicine.medid}
medname = {medicine.medname}
/>
)
return (
<div>
{posts}
</div>
)
}
}
export default Medicines
Below Component is used for Material UI Table
import React from 'react'
import MaterialTable from 'material-table'
class MedicineCard extends React.Component{
render(){
const data=[
{medid:this.props.medid,medname:this.props.medname}
]
const column=[
{
title:'Medicine_ID',field:'medid'
},
{
title:'Medicine_Name',field:'medname'
}
]
return (
<div>
<MaterialTable title="Material Table"
data={data}
column ={column}
/>
</div>
);
}
}
export default MedicineCard
This component is used to display UI
import React from 'react'
import Medicines from './Medicines'
const Test = () => (
<div>
<Medicines />
</div>
)
export default Test
Please help me and guide me out to solve this issue

null is not an object evaluating this.state.<name>

The problem might be common but I am asking because I couldn't fix it. I am getting "null is not an object(evaluating 'this.state.albums')" at line 22
And also I am a bit not clear about the type of data that was returned after the call and how to handle it. Please, can someone help me in explaining this? I am in the learning phase. when I am directly alert the response.data I'm getting [object][object] I have to do JSON stringify to see the data. Why should we do this?
import React, { Component } from 'react';
import {Text} from 'react-native';
import axios from 'axios';
export default class AlbumList extends Component{
constructor(props) {
super(props);
state = { albums : []};
}
componentWillMount(){
console.log('in componentWillMount');
//debugger;
//alert("first"+this.state);
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then((response) => {
//console.log(response);
//alert(JSON.stringify(response));
this.setState({albums : response.data});
//alert(JSON.stringify(this.state.albums));
})
.catch((error) => {
alert(error);
});
}
renderAlbums(){
return this.state.albums.map( album => <Text>{album.title}</Text>); //line 22
}
componentDidMount() {
console.log('I was triggered during componentDidMount')
}
render(){
return(
<Text>{this.renderAlbums()}</Text>
//<Text>Hiii</Text>
);
}
}
You're missing this in your constructor.
constructor(props) {
super(props);
this.state = { albums : []};
}
As for the alert, you can't alert an object it has to be a string. So alerting a JSON object is just [object object]. If you use JSON.stringify it converts the object to a string that can be used for the alert. In your console you can log objects fine, and their structure is more readable. I would stick to console.log for debugging.

Parser data with format json in react

I am new to react.js and I am trying to display data in JSON format in a table. So what I did is:
import React from 'react';
import axios from 'axios';
class TableUser extends React.Component {
constructor(props) {
super(props);
this.state = {
libelle_produit: ''
};
}
componentDidMount(){
axios
.get('admin/prdtId/')
.then(({ data })=> {
this.setState({
libelle_produit: data.libelle_produit
});
})
.catch((err)=> {})
}
render() {
return <div>
<p>{ this.state.libelle_produit }</p>
</div>;
}
}
export default TableUser;
i'd want to be able to access the libelle product of each component and print those on the website
[{"libelle_produit":"test produit"}]
Thanks
<div>
{ this.state.libelle_produit != '' ? this.state.libelle_produit.map( (item, index) =>
<p>{libelle_produit</p>
}
</div>
If the array isnt empty, then loop trough the array and return a p tag with the title of the libelle_produit

React Native, Navigating a prop from one component to another

handleShowMatchFacts = id => {
// console.log('match', id)
return fetch(`http://api.football-api.com/2.0/matches/${id}?Authorization=565ec012251f932ea4000001fa542ae9d994470e73fdb314a8a56d76`)
.then(res => {
// console.log('match facts', matchFacts)
this.props.navigator.push({
title: 'Match',
component: MatchPage,
passProps: {matchInfo: res}
})
// console.log(res)
})
}
I have this function above, that i want to send matchInfo to matchPage.
I take in that prop as follows below.
'use strict'
import React from 'react'
import { StyleSheet, View, Component, Text, TabBarIOS } from 'react-native'
import Welcome from './welcome.js'
import More from './more.js'
export default class MatchPage extends React.Component {
constructor(props) {
super(props);
}
componentWillMount(){
console.log('mathc facts ' + this.props.matchInfo._bodyInit)
}
render(){
return (
<View>
</View>
)
}
}
All the info I need is in that object - 'this.props.matchInfo._bodyInit'. My problem is that after '._bodyInt', I'm not sure what to put after that. I've tried .id, .venue, and .events, they all console logged as undefined...
You never change props directly in React. You must always change the state via setState and pass state to components as props. This allows React to manage state for you rather than calling things manually.
In the result of your api call, set the component state:
this.setState({
title: 'Match',
component: MatchPage,
matchInfo: res
}
Then pass the state as needed into child components.
render() {
return(
<FooComponent title={this.state.title} matchInfo={this.state.matchInfo} />
);
}
These can then be referenced in the child component as props:
class FooComponent extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
console.log(this.props.title);
console.log(this.props.matchInfo);
// Etc.
}
}
If you need to reference these values inside the component itself, reference state rather than props.
this.state.title;
this.state.matchInfo;
Remember components manage their own state and pass that state as props to children as needed.
assuming you are receiving json object as response , you would need to parse the response before fetching the values.
var resp = JSON.parse(matchInfo);
body = resp['_bodyInit'];

How to access JSON in a React Component?

I have a JSON object from a script tag like so:
<script type="text/json" id="json-data">
{'someData': 'Lorem ipsum...'}
</script>
I would like to be able to pull this information and use it within a React component in my render method.
The issue seems to be that I need to set this to a variable within componentWillMount:
export default MyReactComponent extends Component {
componentWillMount() {
const test = document.getElementById('json-data').innerHTML;
}
render() {
return (
<div>
// This is where I would like to use this data.
</div>
);
}
}
Is this the best way to handle passing this data? If so, how can I access this data within the render method of my component?
Thanks!
Store it in the component's state. The render method should only depend this.state and this.props
At the risk of oversimplifying:
this.props are passed from parent components
this.state is state that is internal to the component
Example
export default MyReactComponent extends Component {
componentDidMount() {
this.setState({
test: JSON.parse(document.getElementById('json-data').innerHTML)
});
}
render() {
return <div>{this.state.test}</div>;
},
getInitialState: function() {
return {test: {}}
}
}