componentDidMount() {
this.fetchApi();
}
fetchApi() {
const pointerToThis = this;
const API_KEY = "";
let API_CALL = `https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=${API_KEY}`;
let stockChartXValuesFunction = [];
let stockChartYValuesFunction = [];
fetch(API_CALL)
.then(function (response) {
return response.json();
})
.then(function (data) {
for (var key in data["Time Series(Daily"]) {
stockChartXValuesFunction.push(key);
stockChartYValuesFunction.push(
data["Time Series(Daily"][key]["1. open"]
);
}
// handleClick(e) {
// this.setState({value:e.target.value}, () => {
// console.log(this.state.value); // Updated value here
// });}
pointerToThis.setState({
stockChartXValues: stockChartXValuesFunction,
stockChartYValues: stockChartYValuesFunction,
});
});
}
render() {
return (
<div>
<Plot
data={[
{
x: this.state.stockChartXValues,
y: this.state.stockChartYValues,
type: "scatter",
mode: "lines+markers",
marker: { color: "red" },
},
]}
layout={{ width: 720, height: 440, title: "A Fancy Plot" }}
/>
</div>
);
}
}
export default Stock;
**
Why this.state is not working in render()?**
Is it because of ES6
I am new to ReactJs.I tried a small snippet with React.But this.state is not working in ES6 ReactJs.Help me what I am missing!!
The problem is that you are using function() {...} declarations rather than arrow functions () => {...}.
function declarations rebind this to the function. Where as arrow declarations keep the current this (which is the component).
To fix, just change to this:
fetch(API_CALL)
.then((response) => {
return response.json();
})
.then((data) => {
for (var key in data["Time Series(Daily"]) {
stockChartXValuesFunction.push(key);
stockChartYValuesFunction.push(
data["Time Series(Daily"][key]["1. open"]
);
}
// handleClick(e) {
// this.setState({value:e.target.value}, () => {
// console.log(this.state.value); // Updated value here
// });}
this.setState({
stockChartXValues: stockChartXValuesFunction,
stockChartYValues: stockChartYValuesFunction,
});
});
In your class constructor, you'll also need to bind the fetch method to this:
constructor(props) {
super(props);
this.state = { stockChartXValues: [], stockChartYValues: [], }
this.fetchApi = this.fetchApi.bind(this)
}
Related
In console.log the api fetched data are displaying but in browser itis
showing only white screen. In map function have to update the state function
import React, { Component } from 'react';;
import * as algoliasearch from "algoliasearch";
class App extends React.Component {
constructor() {
super();
this.state = {
data: { hits: [] }
}
// set data to string instead of an array
}
componentDidMount() {
this.getData();
}
getData() {
var client = algoliasearch('api-id', 'apikey');
var index = client.initIndex('');
//index.search({ query:""}, function(data){ console.log(data) })
//index.search({ query:""}, function(data){ console.log("DataRecib=ved. First check this") })
index.search({
query: "",
attributesToRetrieve: ['ItemRate', 'Color'],
hitsPerPage: 50,
},
function searchDone(error, data) {
console.log(data.hits)
});
}
render() {
return (
<div id="root">
{
this.state.data.hits.map(function (data, index) {
return
<h1>{this.setState.data.ItemRate}<br />{data.Color}</h1> >
})}
</div>
);
}
}
//render(<App />, document.getElementById('app'));
export default App;
Couple of mistakes -:
You just need to use this.state.data.ItemRate instead of this.setState.data.ItemRate.
You can get state inside .map using arrow functions ( . )=> { . }
Visit https://www.sitepoint.com/es6-arrow-functions-new-fat-concise-syntax-javascript/
render() {
return (
<div id="root" >
{
this.state.data.hits.map((data,index) => {
return<h1>{this.state.data.ItemRate}<br />{data.Color}</h1>
}
Every this.setState triggers a render() call. If you setState inside render method, you go into an infinity loop.
You want to update this.state.data.hits inside getData() function, then you can display the data like so:
this.state.data.hits.map(data =>
<h1>{data.Color}</h1>
)
For example, if console.log(data.hits) logs out the correct data, then you can:
this.setState({
data: {
hits: data.hits
}
})
EDIT:
Using the code you provided, it should be like this:'
getData = () => {
var client = algoliasearch('A5WV4Z1P6I', '9bc843cb2d00100efcf398f4890e1905');
var index = client.initIndex('dev_twinning');
//index.search({ query:""}, function(data){ console.log(data) })
// index.search({ query:""}, function(data){ console.log("Data Recib=ved. First check this") })
index.search({
query: "",
attributesToRetrieve: ['ItemRate', 'Color'],
hitsPerPage: 50,
}, searchDone = (error, data) => {
this.setState({
data: {
hits: data.hits
}
})
console.log(data.hits)
})
}
I know the state is updating because 1. the 'Loading...' is going away, I can console log this.state.images to see the array. However when the state updates and the loading goes the searchbar shows up but the Card's within CardList do not.
They do show up when I search for a correct string, but not before.
If I pass this.state.images to CardList they show up perfectly. However when I move to the filteredImages they only show up when filtered.
Any ideas? Thanks in advance.
class App extends Component {
constructor() {
super();
this.state = {
images:[],
searchfield: ''
}
}
getLabels = (image) => {
const AuthKey = key.key;
const res = axios.post(`https://vision.googleapis.com/v1/images:annotate?key=${AuthKey}`, {
requests: [
{
image:{
source:{
imageUri: `http://storage.googleapis.com/${image}`
}
},
features:[
{
type:"LABEL_DETECTION",
maxResults:10
}
]
}
]
});
res.then(function (response) {
const results = response.data.responses[0].labelAnnotations;
const ex = results.map(result => {
return result.description;
});
return ex;
});
return res;
};
componentDidMount() {
imageFiles.imageFiles.forEach(img => {
this.getLabels(img).then(result => {
const results = result.data.responses[0].labelAnnotations;
const labels = results.map(result => {
return result.description;
});
//Add new values to the state
this.setState({images:[...this.state.images, {img, labels}]});
});
})
}
onSearchChange = (event) => {
this.setState({searchfield: event.target.value});
}
render() {
const filteredImages = this.state.images.filter(image => {
return image.labels.includes(this.state.searchfield.toLowerCase());
});
// Create an array of objects to store the image path and the labels detected from Google Vision
if (this.state.images.length === 0) {
return <h1>Loading...</h1>
} else {
return (
<Grid className="App">
<SearchBox searchChange={this.onSearchChange}/>
<CardList images={filteredImages} />
</Grid>
)}
}
}
export default App;
class App extends Component {
constructor() {
super();
this.state = {
images:[],
searchfield: '',
filteredImages:[]
}
}
getLabels = (image) => {
const AuthKey = key.key;
const res = axios.post(`https://vision.googleapis.com/v1/images:annotate?key=${AuthKey}`, {
requests: [
{
image:{
source:{
imageUri: `http://storage.googleapis.com/${image}`
}
},
features:[
{
type:"LABEL_DETECTION",
maxResults:10
}
]
}
]
});
res.then(function (response) {
const results = response.data.responses[0].labelAnnotations;
const ex = results.map(result => {
return result.description;
});
return ex;
});
return res;
};
componentDidMount() {
imageFiles.imageFiles.forEach(img => {
this.getLabels(img).then(result => {
const results = result.data.responses[0].labelAnnotations;
const labels = results.map(result => {
return result.description;
});
//Add new values to the state
this.setState({images:[...this.state.images, {img, labels}]});
this.setState({filteredImages:[...this.state.images, {img, labels}]});
});
})
}
onSearchChange = (event) => {
this.setState({searchfield: event.target.value});
let filteredImages = this.state.images.filter(image => {
return image.labels.includes(this.state.searchfield.toLowerCase());
});
this.setState({filteredImages});
}
render() {
// Create an array of objects to store the image path and the labels detected from Google Vision
if (this.state.images.length === 0) {
return <h1>Loading...</h1>
} else {
return (
<Grid className="App">
<SearchBox searchChange={this.onSearchChange}/>
<CardList images={this.state.filteredImages} />
</Grid>
)}
}
}
export default App;
I'm trying to get a simple API call working, where the component calls the API as its mounting and sets the state to be rendered. But when I try to get the state to change an object in it, it says that the state is undefined.
TypeError: Cannot read property 'state' of undefined
class SpellGrid extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
spacing: '16',
username: 'admin',
password: 'notpassword',
description: '',
remember: false,
spell: {
name: '',
school: '',
},
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.mapApiToState = this.mapApiToState.bind(this);
}
mapApiToState() {
// I've tried with all of the axios code in here.
}
componentDidMount() {
axios
.get("http://localhost:8000/api/spells/1")
.then(function(response) {
console.log('response', response);
let fields = response.data[0].fields;
// THIS IS THE LINE THAT IS ERRORING
let spell = Object.assign({}, this.state.spell);
spell.name = fields.Name;
spell.school = fields.School;
console.log('spell', spell);
this.setState({spell});
console.log('state.spell', this.state.spell);
//console.log('state', this.state);
})
.catch(function(error) {
console.log(error);
});
console.log('state', this.state);
}
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
onSubmit = (event) => {
event.preventDefault();
this.props.onSubmit(this.state.username, this.state.password)
};
handleSubmit(e) {
console.log('Form state: ', this.state);
e.preventDefault();
}
render() {
const {classes, theme} = this.props;
const { spacing } = this.state;
return (
<div>{this.state.spell.name}</div>
);
}
} export default withStyles(styles, { withTheme: true })(SpellGrid);
If you are using this, you will need to be carefull in which function scope you're in:
axios
.get("http://localhost:8000/api/spells/1")
.then(response => {
// Since the `response` is now an arrow function, we still
// get access to the original `this`
let fields = response.data[0].fields;
let spell = Object.assign({}, this.state.spell);
spell.name = fields.Name;
spell.school = fields.School;
this.setState({
spell
});
})
.catch(error => {
console.log(error);
});
Trying to calculate width of my scatterplot on the fly so I can pass it as props to my d3 component. I'm having no problem console logging in the handleResize function that is being called by window.addEventListener('resize', this.handleResize) in my ComponentDidMount but I can't setState in the handleResize function or seem to access anything outside of it. I've also tried var self = this; to rebind it but am still getting either a this.setState is not a function or self.setState is not a function.
import React, { PropTypes, Component } from 'react';
import { getDataRange, getTeams, getFile, getAllHitsData, getPlayers} from 'api/index.js';
import {Table, Thead, Th, Tr, Td} from 'components/Reactable';
import Autosuggest from 'react-autosuggest';
import { Link } from 'react-router';
import ScatterChart from 'components/scatterchart';
import DashboardStats from 'components/dashboard-stats';
import DateRangeComponent from 'components/date-range';
import AdminSquare from 'components/admin-square';
import { connect } from 'react-redux';
import { changeStartDate, changeEndDate } from '../../redux/modules/redux-date-change';
import { sendHitData } from '../../redux/modules/send-hit.js';
import { Loading } from 'react-loading';
let allHitDatas = [];
let hitDatas = [];
let teams = [];
// let selectedTeamID = null;
// let selectedTeamName = 'all_teams';
let newFile = '';
// let teamId = '';
let players = [];
let width;
class Dashboard extends Component {
static propTypes = {
team: PropTypes.object.isRequired,
startDate: PropTypes.string.isRequired,
endDate: PropTypes.string.isRequired,
dispatch: PropTypes.func.isRequired
};
static contextTypes = {
router: PropTypes.object
};
constructor(props, context) {
super(props, context);
this.state = {
showRangePicker: false,
hitDatas: [],
teams: [],
start: "",
end: "",
team: this.props.team,
selectedTeamID: null,
selectedTeamName: "",
newFileConfirmation: false,
players: [],
allHitDatas: [],
suggestions: this.getSuggestions(''),
selected: '',
showDatePickerControls: false,
// maxHic: 0
// showScatterPlot: true
};
this.onChange = this.onChange.bind(this);
this.onSuggestionsUpdateRequested = this.onSuggestionsUpdateRequested.bind(this);
}
componentWillReceiveProps() {
this.setState({
maxHic: 0,
team: this.props.team,
selectedTeamID: this.props.team.id,
startDate: this.props.startDate,
endDate: this.props.endDate
// allHitDatas: []
}, () => {
// this.getDomains();
this.dataChangeHelper();
return this.state;
});
}
componentDidMount() {
this.dataChangeHelper();
window.addEventListener('resize', this.handleResize);
getTeams().then((response) => {
teams = response.data;
this.setState({teams: teams});
});
getPlayers().then((response) => {
players = response.data;
this.setState({
players: players
}, () => {
return this.state;
});
});
}
getDomains() {
let dates = [];
let hicArray = [];
console.log(this.state.allHitDatas);
if (this.state.allHitDatas.length === 0) {
return allHitDatas.map((hitData) => {
let date = Date.parse(hitData.EventTime);
dates.push(date);
hicArray.push(hitData.Hic);
let maxDate = Math.max.apply(null, dates);
let maxHic = 0;
let minDate = Math.min.apply(null, dates);
let minHic = 0;
this.setState({
minDate: minDate,
maxDate: maxDate,
minHic: minHic,
maxHic: maxHic
}, () => {
console.log(this.state.maxHic);
return this.state;
});
});
}
return this.state.allHitDatas.map((hitData) => {
let date = Date.parse(hitData.EventTime);
dates.push(date);
hicArray.push(hitData.Hic);
let maxDate = Math.max.apply(null, dates);
let maxHic = Math.max.apply(null, hicArray);
let minDate = Math.min.apply(null, dates);
let minHic = Math.min.apply(null, hicArray);
this.setState({
minDate: minDate,
maxDate: maxDate,
minHic: minHic,
maxHic: maxHic
}, () => {
console.log(this.state.maxHic)
return this.state;
});
});
}
dataChangeHelper() {
const newConfig = {
start: this.props.startDate,
end: this.props.endDate,
team: this.props.team.id
};
getDataRange(newConfig)
.then((response) => {
hitDatas = response.data;
this.setState({
hitDatas: hitDatas
}, () => {
return this.state;
});
});
getAllHitsData(newConfig)
.then((response) => {
allHitDatas = response.data;
this.setState({
allHitDatas: allHitDatas
}, () => {
this.getDomains();
return this.state;
});
});
}
handleResize() {
// const self = this;
let elem = document.getElementById('scatter-chart');
width = elem.offsetWidth * 0.9;
console.log(width);
this.setState({
scatterWidth: width
}, () => {
console.log(this.state.scatterWidth);
});
}
render () {
if (this.state.teams.length === 0 || this.state.players.length === 0) {
return (
<div className="no-data-container">
<div className="no-data-message">We don't have any data for you right now. Would you like
to add some players, teams, or devices?
</div>
<ul className="no-data-links">
<AdminSquare title="PLAYER ADMIN" icon="person" link="/player"/>
<AdminSquare title="TEAM ADMIN" icon="group" link="/team"/>
<AdminSquare title="DEVICE ADMIN" icon="sd_storage" link="/device"/>
</ul>
</div>
);
}
const { value, suggestions } = this.state;
const inputProps = {
placeholder: 'Search for a player',
value,
onChange: this.onChange
};
return (
<div>
<ScatterChart
data={this.state.allHitDatas}
domain={{x: [this.state.minDate, this.state.maxDate], y: [this.state.maxHic, 0]}}
statOneTitle="HIC"
sendHitData={(d) => this.handleImpactClick(d)}
width={ width }
/>
</div>
);
}
}
function mapStateToProps(state) {
console.log(state);
return {
startDate: state.startDate,
endDate: state.endDate
};
}
export default connect(mapStateToProps)(Dashboard);
handleResize doesn't have Dashboard object associated with 'this'. You need to bind to the event hanler
replace window.addEventListener('resize', this.handleResize); with
window.addEventListener('resize',this.handleResize.bind(this));
which will bind the this keyword..so that you can do like this.setState or access any object defined in Dashboard
If you plan on using this inside of a method and the method is not a part of react component's lifecycle, then you need to set it's context to the component instance. In your case you haven't set the correct context for the handleResize, getDomains, dataChangeHelper methods, so the constructor needs some additional bindings:
this.handleResize = this.handleResize.bind(this);
getDomains ...
dataChangeHelper ...
This is the code. No idea as to why there is a problem.
class TeacherForm extends Component {
constructor({ data }) {
super();
this.isUpdatingForm = !! data;
this.state = Object.assign({ ... });
this.handleSubmit = this.handleSubmit.bind(this);
this.removeTeacher = this.removeTeacher.bind(this);
}
handleChange(value, field) {
this.setState({ shouldUpdate: true, [field]: value });
}
handleSubmit(e) {
e.preventDefault();
const { name, subjects, parttime, timing } = this.state;
if (this.isUpdatingForm) {
return update.call({
_id: this.props.data._id,
transaction: { name, subjects, parttime, timing },
}, () => this.setState({ shouldUpdate: false }));
}
return add.call();
}
removeTeacher() {
return remove.call(this.props.data._id);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
...
</form>
);
}
}
The error gets thrown at the handleSubmit method in the callback of update.call. This normally shows up when I call removeTeacher and a list updates and this component unmounts.
It sounds like the callback () => this.setState({ shouldUpdate: false }) is executed after that the component is unmounted. Is that possible? If so, one way to get around that is to replace this part by
return update.call({
_id: this.props.data._id,
transaction: { name, subjects, parttime, timing },
}, () => { !this.unmounted && this.setState({ shouldUpdate: false }); });
and to add
componentWillUnmount() {
this.unmounted = true;
}