map is not a function in react - javascript

I've been trying for three days to solve that I can not put several elements in an array,but if I can put only one When I put in the return this.state.dat.nombre or dat.carrera it works, but if I try to put with the map function I do not get
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dat: [],
isFetch: true
};
}
componentDidMount() {
var url =
"https://cors-anywhere.herokuapp.com/http://sipla.cuci.udg.mx/sc/horariop.php?c=219359735&k=0d8ce4fab5f4df9ce711cae81e044e1a";
fetch(url, {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest"
}
})
.then(response => {
return response.json();
})
.then(art => {
this.setState({ dat: art, isFetch: false });
});
}
render() {
if (this.state.isFetch) {
return "cargando....";
}
this.state.dat.map(art => {
return (
<tr key={art.codigo}>
<td>{art.nombre}</td>
<td>{art.carrera}</td>
<td>{art.horarios}</td>
</tr>
);
});
}
}
export default App;

When I checked your API, I got this data
{
carrera: "INGENIERIA EN COMPUTACION"
ciclo_ingreso: "2019A"
clave_carrera: "INCO"
codigo: "219359735"
cu: "CENTRO UNIVERSITARIO DE LA CIENEGA"
estatus: "ACTIVO"
fecha_consulta: "2019-07-12 12:20:20"
horarios: (4) [{…}, {…}, {…}, {…}]
nivel: "LICENCIATURA"
nombre: "MARIA CECILIA PEREZ PEREZ"
sede: "CAMPUS OCOTLAN"
ultimo_ciclo: "2019B"
}
This is not array. map function for array.
If you want to use this data, you can just write like this.
render() {
if(this.state.isFetch){
return 'cargando....'
}
const {dat} = this.state;
return (
<tr key={dat.codigo}>
<td>{dat.nombre}</td>
<td>{dat.carrera}</td>
<td>{dat.horarios}</td>
</tr>
);
}

Just copy this code and run, you will get desired answer
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dat: [],
isFetch: true
};
}
componentDidMount() {
let dat = []
var url =
"https://cors-anywhere.herokuapp.com/http://sipla.cuci.udg.mx/sc/horariop.php?c=219359735&k=0d8ce4fab5f4df9ce711cae81e044e1a";
fetch(url, {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest"
}
})
.then(response => {
return response.json();
})
.then(art => {
dat.push(art)
this.setState({ dat, isFetch: false });
});
}
render() {
if (this.state.isFetch) {
return "cargando....";
}
this.state.dat.map(art => {
return (
<tr key={art.codigo}>
<td>{art.nombre}</td>
<td>{art.carrera}</td>
<td>{art.horarios}</td>
</tr>
);
});
}
}
export default App;```

Related

componentDidMount() State Change in Context Provider not triggering re-render on Child Components

Here is my code. Been trying to get this to work for 4 days now. I've tried everything from function Components to class Components, to everything in between. At my wits' end. I can't set the state properly in the constructor because it's asynchronous but it doesn't re-render when put in componentDidMount()
EDIT: Yes i know some of the code is redundant. I changed it around to isolate the bug and removed the addParams() logic as well as some other things.
import React, { Component } from "react";
import axios from "axios";
export const ListContext = React.createContext();
class ListContextProvider extends Component {
constructor() {
super();
this.state = { cards: {}, params: {} };
}
addParams(parameters) {
return parameters;
}
getCards() {
let parameters = this.addParams({ last_name__icontains: "smith" });
console.log(parameters);
axios({
method: "get",
url: "http://127.0.0.1:8000/charges/cardsapi/",
params: parameters,
}).then((response) => {
let cards = Object.values(response.data.results);
let cardsState = Object.assign({}, cards);
this.setState({ cards: cardsState });
console.log(this);
console.log(this.state);
});
}
componentDidMount() {
console.log("mounted");
this.getCards();
}
render() {
return (
<ListContext.Provider value={this.state}>
{this.props.children}
</ListContext.Provider>
);
}
}
export { ListContextProvider };
and then the Consumer:
export default function DataTable(context) {
let cards = context;
const rows = [];
const headerCells = [];
if (cards.length > 1) {
for (let field in cards[0]) {
headerCells.push(<TableCell key={field}>{field}</TableCell>);
}
for (let row of cards) {
const cells = [];
for (const [key, value] of Object.entries(row)) {
cells.push(<TableCell key={key}>{value}</TableCell>);
}
rows.push(<TableRow key={cells[0].props.children}>{cells}</TableRow>);
}
return (
<Table>
<TableHead>
<TableRow key={"header"}>{headerCells}</TableRow>
</TableHead>
<TableBody>{rows}</TableBody>
</Table>
);
} else {
return (
<Table>
<tbody>
<tr>
<td>Empty</td>
</tr>
</tbody>
</Table>
);
}
}
This worked:
import React, { Component } from "react";
import axios from "axios";
let ListContext = React.createContext();
class ListContextProvider extends Component {
constructor() {
super();
this.state = { cards: [], params: {} };
}
addParams(parameters) {
this.setState({ params: parameters });
}
getCards() {
let parameters = this.state.params;
console.log(parameters);
axios({
method: "get",
url: "http://127.0.0.1:8000/charges/cardsapi/",
params: parameters,
}).then((response) => {
let cardsState = Object.values(response.data.results);
this.setState({ cards: cardsState });
});
}
async componentDidMount() {
await this.addParams({ last_name__icontains: "shaer" });
console.log("mounted");
this.getCards();
}
render() {
return (
<ListContext.Provider value={this.state}>
{this.props.children}
</ListContext.Provider>
);
}
}
export { ListContextProvider, ListContext };

Uncaught TypeError: Cannot convert undefined or null to object React JS

I am trying to get my photo blog/phlog manager component functional. However the console says the there an undefined object through props.
import React, { Component } from 'react';
import axios from 'axios';
import DropzoneComponent from 'react-dropzone-component';
import "../../../node_modules/react-dropzone-component/styles/filepicker.css";
import "../../../node_modules/dropzone/dist/min/dropzone.min.css";
class PhlogEditor extends Component {
constructor(props) {
super(props);
this.state = {
id: '',
phlog_status: '',
phlog_image: '',
editMode: false,
position: '',
apiUrl: 'http://127.0.0.1:8000/phlogapi/phlog/',
apiAction: 'post'
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.componentConfig = this.componentConfig.bind(this);
this.djsConfig = this.djsConfig.bind(this);
this.handlePhlogImageDrop = this.handlePhlogImageDrop.bind(this);
this.deleteImage = this.deleteImage.bind(this);
this.phlogImageRef = React.createRef();
}
deleteImage(event) {
event.preventDefault();
axios
.delete(
`http://127.0.0.1:8000/phlogapi/phlog/${this.props.id}/delete`,
{ withCredentials: true }
)
.then(response => {
this.props.handlePhlogImageDelete();
})
.catch(error => {
console.log('deleteImage failed', error)
});
}
The error is occuring at Object.keys(this.props.phlogToEdit).length>0
componentDidUpdate() {
if (Object.keys(this.props.phlogToEdit).length > 0) {
// debugger;
const {
id,
phlog_image,
phlog_status,
position
} = this.props.phlogToEdit;
this.props.clearPhlogsToEdit();
this.setState({
id: id,
phlog_image: phlog_image || '',
phlog_status: phlog_status || '',
position: position || '',
editMode: true,
apiUrl: `http://127.0.0.1:8000/phlogapi/phlog/${this.props.id}/update`,
apiAction: 'patch'
});
}
}
handlePhlogImageDrop() {
return {
addedfile: file => this.setState({ phlog_image_url: file })
};
}
componentConfig() {
return {
iconFiletypes: [".jpg", ".png"],
showFiletypeIcon: true,
postUrl: "https://httpbin.org/post"
};
}
djsConfig() {
return {
addRemoveLinks: true,
maxFiles: 3
};
}
buildForm() {
let formData = new FormData();
formData.append('phlog[phlog_status]', this.state.phlog_status);
if (this.state.phlog_image) {
formData.append(
'phlog[phlog_image]',
this.state.phlog_image
);
}
return formData;
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
handleSubmit(event) {
axios({
method: this.state.apiAction,
url: this.state.apiUrl,
data: this.buildForm(),
withCredentials: true
})
.then(response => {
if (this.state.phlog_image) {
this.phlogImageRef.current.dropzone.removeAllFiles();
}
this.setState({
phlog_status: '',
phlog_image: ''
});
if (this.props.editMode) {
this.props.handleFormSubmission(response.data);
} else {
this.props.handleSuccessfulFormSubmission(response.data);
}
})
.catch(error => {
console.log('handleSubmit for phlog error', error);
});
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit} className='phlog-editor-wrapper'>
<div className='one-column'>
<div className='image-uploaders'>
{this.props.editMode && this.props.phlog_image_url ? (
<div className='phlog-manager'>
<img src={this.props.phlog.phlog_image_url} />
<div className='remove-image-link'>
<a onClick={() => this.deleteImage('phlog_image')}>
Remove Photos
</a>
</div>
</div>
) : (
<DropzoneComponent
ref={this.phlogImageRef}
config={this.componentConfig()}
djsConfig={this.djsConfig()}
eventHandlers={this.handlePhlogImageDrop()}
>
<div className='phlog-msg'>Phlog Photo</div>
</DropzoneComponent>
)}
</div>
<button className='btn' type='submit'>Save</button>
</div>
</form>
);
}
}
export default PhlogEditor;
I do not understand how the object is empty when the props are coming from the parent component
phlog-manager.js:
import React, { Component } from "react";
import axios from "axios";
import PhlogEditor from '../phlog/phlog-editor';
export default class PhlogManager extends Component {
constructor() {
super();
Here I define phlogToEdit as an object to pass as props to phlogEditor child component
this.state = {
phlogItems: [],
phlogToEdit: {}
};
this.handleNewPhlogSubmission = this.handleNewPhlogSubmission.bind(this);
this.handleEditPhlogSubmission = this.handleEditPhlogSubmission.bind(this);
this.handlePhlogSubmissionError = this.handlePhlogSubmissionError.bind(this);
this.handleDeleteClick = this.handleDeleteClick.bind(this);
this.handleEditClick = this.handleEditClick.bind(this);
this.clearPhlogToEdit = this.clearPhlogToEdit.bind(this);
}
clearPhlogToEdit() {
this.setState({
phlogToEdit: {}
});
}
handleEditClick(phlogItem) {
this.setState({
phlogToEdit: phlogItem
});
}
handleDeleteClick(id) {
axios
.delete(
`http://127.0.0.1:8000/phlogapi/phlog/${id}`,
{ withCredentials: true }
)
.then(response => {
this.setState({
phlogItems: this.state.phlogItems.filter(item => {
return item.id !== id;
})
});
return response.data;
})
.catch(error => {
console.log('handleDeleteClick error', error);
});
}
handleEditPhlogSubmission() {
this.getPhlogItems();
}
handleNewPhlogSubmission(phlogItem) {
this.setState({
phlogItems: [phlogItem].concat(this.state.phlogItems)
});
}
handlePhlogSubmissionError(error) {
console.log('handlePhlogSubmissionError', error);
}
getPhlogItems() {
axios
.get('http://127.0.0.1:8000/phlogapi/phlog',
{
withCredentials: true
}
)
.then(response => {
this.setState({
phlogItems: [...response.data]
});
})
.catch(error => {
console.log('getPhlogItems error', error);
});
}
componentDidMount() {
this.getPhlogItems();
}
render() {
return (
<div className='phlog-manager'>
<div className='centered-column'>
This is where the object, phlogToEdit is being passed as props to child component mentioned
<PhlogEditor
handleNewPhlogSubmission={this.handleNewPhlogSubmission}
handleEditPhlogSubmission={this.handleEditPhlogSubmission}
handlePhlogSubmissionError={this.handleEditPhlogSubmission}
clearPhlogToEdit={this.clearPhlogToEdit}
phlogToEdit={this.phlogToEdit}
/>
</div>
</div>
);
}
}
#Jaycee444 solved the problem it was the parent component!
phlogToEdit={this.state.phlogToEdit}

How to loop in render with array data API React

I have data from API where when I use console log I read all data.
When I want to rendering this data I see only the first index of the array.
API look like this:
aladinModel: (2) […]
​​
0: (48) […]
​​​
0: Object { DATS: "2019-10-20T23:00:00.000Z", TA: 12.1, RH: 93.3, … }
​​​
1: Object { DATS: "2019-10-21T02:00:00.000Z", TA: 11, RH: 95.1, … }
​​​
2: Object { DATS: "2019-10-21T05:00:00.000Z", TA: 12.4, RH: 96.5, … }
I want to display all values.
My code:
import React from "react";
export default class FetchRandomUser extends React.Component {
state = {
loading: true,
dataAPI: null
};
async componentDidMount() {
const url = "http://localhost:8000/?date=2019-10-26&station=1010&daysForward=5";
const response = await fetch(url);
const data = await response.json();
console.log(data);
this.setState({ dataAPI: data.aladinModel[0], loading: false });
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.dataAPI) {
return <div>Няма данни !</div>;
}
return (
<div>
<div>{this.state.dataAPI[0].DATS}</div>
</div>
);
}
}
constructor(props) {
super(props);
this.state = {
loading: true,
dataAPI: null
};
}
async componentDidMount() {
fetch("http://localhost:8000/?date=2019-10-26&station=1010&daysForward=5")
.then(response => response.json())
.then(data => {
return data;
})
.catch(error => console.log(error));
this.setState({ dataAPI: this.data, loading: false });
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.dataAPI) {
return <div>Няма данни !</div>;
}
return this.state.dataAPI.map((data, i) => (
<div key={i}>
{data.DATS},{data.TA},{data.RH}
</div>
));
}

React-Native | Problem with setState can't be read

The setState can't be read, the value of print1 stays 0000 it must be changed to array[0].date and the alert shows the value of array[0].date
the problem is that it works before.
PS: there's no error shown
export default class WebServiceUse extends Component {
constructor(props) {
super(props);
this.state = ({
print1: '0000',
})
}
componentDidMount() {
fetch('https://**********', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: '1' })
}).then((response) => response.json()).then((responseJson) => {
let array = responseJson.ed5aaf3d933385698d872d0a0d5d4f36
alert(array[0].date)
this.setState = ({
print1: array[0].date,
})
})
.catch((error) => {
console.error(error)
});
}
render() {
return (
<View style={styles.container}>
<Text>Test:</Text>
<Text>{this.state.print1}</Text>
</View>
);
}
}
When you set the state in the constructor, this.state = is assigning the initial value of the state object so it's not really a function. Further down the lifecycle calling this.setState IS a function that merges existing state with your changes. So change
this.state = ({
print1: '0000',
})
to
this.state = {
print1: '0000'
}
Also you're not assigning state, you're calling the function so don't use =
this.setState = ({
print1: array[0].date,
})
ought to be
this.setState({
print1: array[0].date
})
Try doing this
export default class WebServiceUse extends Component {
constructor(props) {
super(props);
this.state = ({
print1: '0000',
})
}
componentDidMount() {
var that = this;
fetch('https://**********', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: '1' })
}).then((response) => response.json()).then((responseJson) => {
let array = responseJson.ed5aaf3d933385698d872d0a0d5d4f36
alert(array[0].date)
that.setState({
print1: array[0].date,
})
})
.catch((error) => {
console.error(error)
});
}
render() {
return (
<View style={styles.container}>
<Text>Test:</Text>
<Text>{this.state.print1}</Text>
</View>
);
}
}

Is there a way to continuously get an value from a redux store one at a time? react redux

i have a async fetch that gets values like A001, A002, names and so on from an API. But sometimes i get 3 or more values with 1 api fetch and i loose some because i show only 3 values at a time in my react component.
So i look for a way to continuously show 1 entry from the store for like 2 seconds and then the next entry and so on.
Can someone please help me here?
Actions
let lastId = 0;
let pathArray = window.location.pathname.split('/');
export const fetchLastId = () => dispatch => {
const url = '/api/display/sites/' + pathArray[3] + '/displays/' + pathArray[5] + '/show';
fetch(url, {
method: 'GET',
mode: 'cors',
headers: {
'Authorization': ''
},
'Content-Type': 'application/json'
}).then(function(response) {
return response.json();
}).then(function(data) {
if (data.length) {
lastId = data[0].id;
} else {
lastId = 0;
}
console.log('Die Letzte ID war ' + lastId);
}).catch(function(error) {
console.log('Fehler: ', error);
})
}
export const fetchLastCalls = () => dispatch => {
const url = '/api/display/sites/' + pathArray[3] + '/displays/' + pathArray[5] + '/calls?id_greater_than=' + lastId;
fetch(url, {
method: 'GET',
mode: 'cors',
headers: {
'Authorization': ''
},
'Content-Type': 'application/json'
}).then(function(response) {
return response.json();
}).then(function(data) {
data.reverse();
if (data.length) {
for (let item of data) {
switch (item.service_id) {
case 24:
dispatch({ type: 'SERVICE_1', payload: item })
break;
case 25:
dispatch({ type: 'SERVICE_2', payload: item })
break;
default:
console.log('Aufruf im Falschen Dienst getätigt.')
}
lastId = item.id;
}
} else {
console.log('Keine neuen Aufrufe.');
}
}).catch(function(error) {
console.log('Fehler: ', error);
})
}
Reducer
let initialState = [];
function service1(state = initialState, action) {
if (action.type === 'SERVICE_1') {
return [action.payload, ...state];
}
return state;
}
export default service1;
Container
import React from 'react';
import { connect } from 'react-redux';
import { NewCall } from '../components/NewCall';
import { LastCall } from '../components/LastCall';
import { fetchLastId , fetchLastCalls } from '../actions/index';
class Service1 extends React.Component {
componentWillMount() {
this.props.onFetchLastId();
}
componentDidMount() {
setInterval(function() {
this.props.onFetchLastCalls();
}.bind(this), 1000);
}
renderNewTicket() {
return this.props.calls.map(call => {
return (
<p key={call.ticket}>{call.ticket}</p>
);
});
}
renderNewPlace() {
return this.props.calls.map(call => {
return (
<p key={call.desk_id}>{call.desk_id}</p>
);
});
}
renderLastTicket() {
return this.props.calls.map(call => {
return (
<p key={call.ticket}>{call.ticket}</p>
)
})
}
renderLastPlace() {
return this.props.calls.map(call => {
return (
<p key={call.desk_id}>{call.desk_id}</p>
)
})
}
componentDidUpdate() {
}
render() {
return(
<div>
<NewCall
call={ this.renderNewTicket() }
place={ this.renderNewPlace() }
/>
<LastCall
call={ this.renderLastTicket() }
place={ this.renderLastPlace() }
rollOn={1}
/>
<LastCall
call={ this.renderLastTicket() }
place={ this.renderLastPlace() }
rollOn={2}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
calls: state.service1
};
}
let mapDispatchToProps = {
onFetchLastId: fetchLastId,
onFetchLastCalls: fetchLastCalls
}
export default connect(mapStateToProps, mapDispatchToProps)(Service1);
1 Output Component
import React from 'react';
import { Textfit } from 'react-textfit';
import Blink from './Blink';
const inlineStyle = {
width: 945,
height: 249
};
export class NewCall extends React.Component {
render() {
return(
<div>
<div className="flex-item-grey ticketNrGr">
<Textfit mode="multi" style={inlineStyle} className="textfit" max={200}><Blink>{this.props.call[0]}</Blink></Textfit>
</div>
<div className="flex-item-grey platzNrGr">
<Textfit mode="multi" style={inlineStyle} className="textfit" max={200}><Blink>{this.props.place[0]}</Blink></Textfit>
</div>
</div>
);
}
}
Second Output Component
import React from 'react';
import { Textfit } from 'react-textfit';
const inlineStyleCall = {
width: 735,
height: 195
};
const inlineStyleDesk = {
width: 200,
height: 195
};
export class LastCall extends React.Component {
render() {
return(
<div className="flex-container-aufrufKl">
<div className="flex-item-grey ticketNrKl">
<Textfit mode="multi" style={inlineStyleCall} className="textfit" max={200}>{this.props.call[this.props.rollOn]}</Textfit>
</div>
<div className="flex-item-grey platzNrKl">
<Textfit mode="multi" style={inlineStyleDesk} className="textfit" max={200}>{this.props.place[this.props.rollOn]}</Textfit>
</div>
</div>
);
}
}
It sounds to me like it should be the responsibility of the component to trigger a new action to render the next available value. So you could have a component that accepts the value value and a boolean indicating if there are any more values: hasMoreValues.
In your react component, you'll need to make it a class to access the lifecycle hooks and hook into the componentDidMount function:
class MyComponent extends Component {
constructor(props) {
super(props)
}
componentDidMount() {
if(this.props.hasMoreValues) {
setTimeout(this.props.showNextValue, 2000)
}
}
render() {
return (
<div>{this.props.value}</div>
)
}
}
export default connect(
(props) => ({
hasMoreValues: getHasMoreValues(),
value: getNextValue(),
)},
{
showNextValue: () => { type: 'SHOW_NEXT_ACTION' },
},
)
An approach like this means that the trigger is still coming from the application. The next thing to do is update the item to view to be the next one available in your reducer, but I'll leave that up to you.

Categories

Resources