I've got a problem with my ReactJS App with getting data from api. I still have an error: 'Cannot read property 'map' of undefined', and I have no idea why it's happening.
My code:
UsersList.js
import React from 'react';
import ReactDOM from 'react-dom';
import fetch from 'isomorphic-fetch';
import { Card, Container, Icon } from 'semantic-ui-react'
import User from './User'
class ProfilesList extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
fetched: false,
loading: false,
};
}
componentWillMount(){
this.setState({
loading : true
});
fetch('http://58be98154389c312007f403f.mockapi.io/users/users').then(res => res.json())
.then(res =>{
this.setState({
users : res.results,
loading : true,
fetched : true
});
});
}
render() {
const {fetched, loading, users} = this.state;
let content;
if(fetched){
content = <div>{this.state.users.map((user,index) =>
<User key={user.username} id={index+1} user={user}/>)}</div>;
}
else if(loading && !fetched){
content = <p> Loading ...</p>;
}
else{
content = (<div></div>);
}
return (
<div>
{content}
</div>
);
}
}
export default ProfilesList;
User.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Card, Container, Icon } from 'semantic-ui-react'
class User extends React.Component {
render() {
const {user, id} = this.props;
return (
<Card
image='http://semantic-ui.com/images/avatar/large/elliot.jpg'
header={user.username}
meta='Friend'
description='Elliot is a sound engineer living in Nashville who enjoys playing guitar and hanging with his cat.'
extra={(
<a>
<Icon name='user' />
16 Friends
</a>
)}
/>
);
}
}
export default User;
Thanks for your help!
Your state.users is undefined when you try to do this.state.users.map() in your render function. So task #1 is to figure out why your fetch() is returning undefined and fix that. It's a good idea to build in some handling for cases when you get undefined results or other errors and set your state appropriately. Additionally, I tend to check that an expected array is not undefined before I try to map it, like this:
{
expectedArray
?
expectedArray.map(someMappingFunction)
:
<div>expectedArray was 'undefined' or otherwise 'falsy'</div>
}
Such a conditional statement is called a "ternary" and is very useful because it can be embedded in JSX as an "if/else" statement. It has the form (condition) ? (expression if true) : (expression if false). For example:
var foo = 7;
var bar = (foo % 2 == 0) ? "Even" : "Odd";
console.log(bar); // "Odd"
Related
Hello I'm a beginner of react, I'm stuck Cannot read the property 'map' of undefined, I understand is a type error please help me.
import React, { Component } from 'react';
import Message from "./Message";
class MessageList extends Component {
render() {
const { messages } = this.props;
return messages.map(message => (
<ul>
<Message message={message} />
</ul>
));
}
}
export default MessageList;
To u can try to use the "null object” pattern to avoid such errors when the prop is not uet to be sent to the component, the issue is not coming from the code you showed us so we cant help you find the main problem
Null object pattern Inside of the render method (also in this case is a default param):
const { messages = [] } = this.props;
As suggested messages can be null in which case map will throw an error.
However, you also haven't constructed props which means messages will always be null.
import React, { Component } from 'react';
import Message from "./Message";
class MessageList extends Component {
constructor(props) {
super(props);
// state if you need it.
this.state = { counter: 0 };
}
render() {
const { messages } = this.props;
return messages && messages.map(message => (
<ul>
<Message message={message} />
</ul>
));
}
}
export default MessageList;
Tested and this works.
I want to pass a state using react navigator. I want to pass showing: false, so my progress bar component will disappear.Can someone please explain how I can do this. Thanks so much.
Here is my code.
import React, { Component } from "react";
import { Button, View, Text, TextInput } from "react-native";
import ContinueButton from "./ContinueButton";
import { CreateAboutMe } from "./StyleSheet/AboutMeStyle";
import * as Progress from "react-native-progress";
export class AboutUser extends Component {
constructor(props) {
super(props);
this.navigatToInterests = this.navigatToInterests.bind(this);
this.checkEntry = this.checkEntry.bind(this);
this.state = {
value: "",
showing: true,
};
}
navigatToInterests = ({ navigation }) => {
let checkDescription = this.state.value;
if (checkDescription === "") {
alert("Please tell people about yourself");
} else {
this.props.navigation.navigate("Interests");
}
};
checkEntry = (Description, value) => {
this.setState({ value: value });
console.log(this.state.value);
};
render() {
return (
<View style={CreateAboutMe.overAllContainer}>
{this.state.showing && (
<Progress.Bar
progress={0.7667}
width={300}
color={"red"}
style={CreateAboutMe.progressbar}
showing={this.state.showing}
/>
)}
Which version of React Navigation are you using?
In version 4, you can send some data using the second argument of the navigate function like this:
this.props.navigation.navigate("Interests",{"someKey":"someValue", ...});
Then you can grab the data in the next page through the props:
let someValue = this.props.navigation.getParam('someKey');
I'm using ReactJS higher order function to enhance the existing component with API fetching capability together with loading , error views.In order to become more reusable , I wish another programmer who use my HOC to be able to add customize loading , error views like this.
var FetchTest = fetchableContainer({
url:"https://jsonplaceholder.typicode.com/posts",
loadingView: <div>..Custom Loading..</div>,
noConnectionView: <div>.. Custom no connection view .. </div>,
errorView: <div>Custom Error View</div>
})(TestComponent);
Unfortunately , it shows error Message .
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: object.
Can someone tell me another solutions with clean and elegant code.Here is my fetchableContainer.
import React, {Component} from 'react';
import axios from 'axios';
import loadingView from './loadingView.js';
import errorView from './errorView.js';
import noDataView from './noDataView.js';
import noConnectionView from './noConnectionView.js';
//redux imports
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { Link } from 'react-router';
const fetchableContainer = (json) => (BaseComponent) => {
let url = json.url || "";
let loadingView = json.loadingView || loadingView;
let errorView = json.errorView || errorView;
let noConnectionView = json.noConnectionView || noConnectionView;
let noDataView = json.noDataView || noDataView;
class FetchableContainer extends React.Component{
constructor(props){
super(props);
this.state = {
fetchData: null,
loading: false,
fetchError: null,
interntConnection: navigator.onLine?true:false,
};
}
componentDidMount(){
this.setState({loading: true});
axios.get(this.url,{
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
}).then((response)=>{
this.setState({fetchData: response.data});
this.setState({loading: false});
}).catch((error)=>{
console.log("Erorr happen");
console.log(error);
this.setState({fetchError: error});
});
}
render(){
if(!this.state.interntConnection){
return <this.noConnectionView/>;
}
if(this.state.loading){
return <this.loadingView/>;
}
if(this.state.fetchError){
return <this.errorView/>;
}
return (
<BaseComponent {...this.props}{...this.state}/>
);
}
}
}
export default fetchableContainer;
Firstly, your FetchTest is undefined because the fetchableContainer doesn't return anything! Technically, it returns a function which returns nothing. You should return the class if you actually want to use it.
Also, this seems a strange way to create a component. Currently, it would be equivalent to do this:
var FetchTest = fetchableContainer({
url:"https://jsonplaceholder.typicode.com/posts",
loadingView: <div>..Custom Loading..</div>,
noConnectionView: <div>.. Custom no connection view .. </div>,
errorView: <div>Custom Error View</div>
}, TestComponent);
Container:
//...
const fetchableContainer = (json, BaseComponent) =>
class FetchableContainer extends React.Component {
//...
}
}
export default fetchableContainer;
The error message is probably displayed because you are trying to use the undefined FetchTest in some code that you haven't posted.
I would recommend creating a React Container in the standard way (https://redux.js.org/basics/usage-with-react#implementing-container-components) and passing in the parameters you need as props.
For example, it might look a little like this:
// Imports etc...
class FetchableContainer extends React.Component {
// ...
render() {
//...
return this.props.BaseComponent(/* Props */);
}
}
export default FetchableContainer;
I just found the error.This is because I was passing the JSX component and trying to fetch that JSX component.The error was solved by passing the function that return JSX component and fetch that function on render method of FetchableContainer like this.
var FetchTest = fetchableContainer({
url: 'https://jsonplaceholder.typicode.com/posts/',
errorView: ()=> <div>Custom Error View</div>,
LoadingView:()=><div>Custom loading</div> ,
NoConnectionView: ()=> <div>Custom no Connection</div>
})(TestComponent);
My Final code for FetchableContainer is as follow.
import React, {Component} from 'react';
import axios from 'axios';
import LoadingView from './LoadingView';
import ErrorView from './ErrorView';
import NoDataView from './NoDataView';
import NoConnectionView from './NoConnectionView';
//redux imports
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { Link } from 'react-router';
const fetchableContainer = (json) => (BaseComponent) =>{
let LoadingFetchView = json.LoadingView || LoadingView;
let fetchUrl = json.url || "https://jsonplaceholder.typicode.com/posts/";
let ErrorFetchView = json.ErrorView || ErrorView;
let NoConnectionFetchView = json.NoConnectionView || NoConnectionView;
let NoDataFetchView = json.NoDataView || NoDataView;
class FetchableContainer extends React.Component{
constructor(props){
console.log("inside constructure");
console.log(LoadingView);
super(props);
this.state = {
fetchData: null,
loading: false,
fetchError: null,
interntConnection: navigator.onLine?true:false,
};
}
componentDidMount(){
this.setState({loading: true});
axios.get(fetchUrl,{
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
}).then((response)=>{
this.setState({fetchData: response.data});
this.setState({loading: false});
}).catch((error)=>{
console.log("Erorr happen");
console.log(error);
this.setState({fetchError: error});
});
}
render(){
if(!this.state.interntConnection){
return <NoConnectionFetchView/>;
}
if(this.state.loading){
return <LoadingFetchView/>;
}
if(this.state.fetchError){
return <ErrorFetchView/>;
}
return (
<BaseComponent {...this.props}{...this.state}/>
);
}
}
return FetchableContainer;
}
export default fetchableContainer;
I have defined cookie in my project like this.
import cookie from 'react-cookie'. So that means I have defined cookie so I shouldn't be getting that error but sitll I am getting it.. I will share my code if anyone thinks it's needed.
EDIT
I om only adding here half of the code since I have to add some more details with the full code And I have no I idea what to add. The full code can be found here https://pastebin.com/APTdX879
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Block from "./Block"
import Add from './Add'
import cookie from 'react-cookie'
class App extends Component {
constructor(props){
super(props)
this.state = {
logedin: cookie.load("logedin")
}
}
submit(){
fetch("/newaccount")
.then(res=>res.json())
.then(data=>{
console.log(data)
console.log(document.getElementById('username').value)
let arr = data.filter(event=>{
return (event.username==document.getElementById('username').value&&event.password==document.getElementById('password').value)
})
console.log(arr.length)
console.log(arr)
if(arr.length==1){
this.setState({logedin:true})
}
else{
alert("wrong useranme or password")
}
})
}
componentDidMount(){
fetch("/api")
.then(response=>response.json())
.then(data=> this.setState({data: data}))
.catch(error=>console.log(error+' 1'))
}
componentWillMount() {
}
render() {
if(!this.state.logedin){
return (
<div>
<input id="username"/>
<input id='password' type="password"/>
<button onClick={this.submit.bind(this)}>Submit</button>
</div>
)
}
if(!this.state.data){
return <p>loading</p>
}
return (
<div>
<hr/>
<Add/>
{
this.state.data.map((data,i)=>{
return(
<div key={i+"a"}>
<Block name={data.username} img={data.img} date={data.date} text={data.text} likes={data.likes} comments={data.comments} key={i} id={data._id}></Block>
<br key={i+"b"}/>
</div>
)
})
}
</div>
*Second EDIT here is a screenshot of the error http://prntscr.com/gghb5p .
According to the react-cookie documentation at https://www.npmjs.com/package/react-cookie you should import it like this:
import { CookiesProvider, withCookies, Cookies } from 'react-cookie';
And then getting a cookie in the constructor won't work, you will need to do it in the componentWillMount() method like this:
componentWillMount() {
const { cookies } = this.props;
this.state = {
name: cookies.get('name') || 'Ben'
};
}
try to inject it first:
import { withCookies } from 'react-cookie';
export default withCookies(App);
or
App = withCookies(App);
and then in your constructor:
this.state = {
logedin: props.cookies.get("logedin")
}
EDIT: in documentation of react-cookie there is no load method, I think you need
logedin: props.cookies.get("logedin")
There aren't many useful React Higher-Order-Component (HOC) examples out there that I could find and the simple ones that exists are so simplistic they do not really even scratch the surface of what can or cannot be done using HOC's. Anyway, from what I could find, I tried the following and I am sure I am mssing something (probably obvious) because this is my first attempt to try and use HOC's:
HOC:
import { Component, PropTypes } from 'react'
export const WizardWrapper = Step => class extends Component {
constructor(props) {
super(props)
this.nextPage = this.nextPage.bind(this)
this.previousPage = this.previousPage.bind(this)
this.state = {
page: 1
}
}
nextPage() {
this.setState({ page: this.state.page + 1 })
}
previousPage() {
this.setState({ page: this.state.page - 1 })
}
goToPage(page) {
this.setState({ page })
}
render() {
const { onSubmit, submitButtonText, step} = this.props
let hasNext = this.props.step > this.state.page
let hasPrev = this.state.page < this.props.step
let nextText = hasNext ? 'Next' : submitButtonText
return (
<Step previousPage={hasPrev ? this.previousPage : null}
onSubmit={hasNext ? this.nextPage : onSubmit}
{...this.state} {...this.props}/>
)
}
}
Some Component:
export const WizardPage = (props) => <h1>Some page</h1>
Attempt to display wrapped component (even if wrapping it does not actually do anything just yet):
import { Component, PropTypes } from 'react'
import {WizardWrapper} from 'common/client/components/wizard/WizardWrapper'
import {WizardPage} from 'common/client/components/wizard/WizardPage'
export default class FormTest extends Component {
render() {
let WrapperPage = WizardWrapper(WizardPage)
return (
<div>
{WrapperPage}
</div>
)
}
}
I don't get any errors, but nothing is displayed either. Any ideas what I am missing or doing wrong?
TIA!
In case anyone else runs into this, in my case I started seeing browser console logs with:
maxAge 50 1 VM611:1
maxAge 50 2 VM611:1
maxAge 50 3 VM611:1
I did some digging and found out these were likely coming from NPM's LRU cache, so I ran npm cache clean from the console. The errors went away and my HOC's finally started displaying as expected. Apparently a corrupt NPM cache was the culprit.