React.js on Rails error - javascript

I am following this tutorial on how to integrate react.js into rails and when I pre compile my assets I get an error with this code stating that (data) => this.setState({statuses: data}); causes SyntaxError: unknown: Unexpected token (14:44) I tried many things to get it to work and when I delete the semi-colon at the end it works except that the interval no longer gets called the console will say alert twice when the page is refreshed and then never again.
var StatusesContainer = React.createClass ({
componentWillMount() {
this.fetchStatuses();
setInterval(this.fetchStatuses(), 1000);
},
fetchStatuses() {
console.log("alert");
$.getJSON(
this.props.statusesPath,
{
space_id: this.props.space_id
},
(data) => this.setState({statuses: data});
);
},
getInitialState() {
return ({ statuses: [] });
},
render() {
return (<RecentStatuses statuses={ this.state.statuses }/>);
}
});

$.getJSON(
this.props.statusesPath,
{
space_id: this.props.space_id
},
(data) => this.setState({statuses: data});
);
Here is the problem: (data) => this.setState({statuses: data});, you should use , not ;

Related

Vue-cli project data update delays when sending request with Vuex and axios

I'm working on a project with Vue-CLI, and here's some parts of my code;
//vuex
const member = {
namespaced:true,
state:{
data:[]
},
actions:{
getAll:function(context,apiPath){
axios.post(`http://localhost:8080/api/yoshi/backend/${apiPath}`, {
action: "fetchall",
page: "member",
})
.then(function(response){
context.commit('displayAPI', response.data);
});
},
toggle:(context,args) => {
return axios
.post(`http://localhost:8080/api/yoshi/backend/${args.address}`,
{
action:"toggle",
ToDo:args.act,
MemberID:args.id
})
.then(()=>{
alert('success');
})
},
},
mutations:{
displayAPI(state, data){
state.tableData = data;
},
},
getters:{
getTableData(state){
return state.tableData
}
}
}
//refresh function in member_management.vue
methods: {
refresh:function(){
this.$store.dispatch('member/getAll',this.displayAPI);
this.AllDatas = this.$store.getters['member/getTableData'];
}
}
//toggle function in acc_toggler.vue
ToggleAcc: function (togg) {
let sure = confirm(` ${todo} ${this.MemberName}'s account ?`);
if (sure) {
this.$store
.dispatch("member/toggle", {
address: this.displayAPI,
id: this.MemberID,
act: togg,
Member: this.MemberName,
})
.then(() => {
this.$emit("refresh");
});
}
},
The acc_toggler.vue is a component of member_management.vue, what I'm trying to do is when ToggleAcc() is triggered, it emits refresh() and it requests the updated data.
The problem is , after the whole process, the data is updated (I checked the database) but the refresh() funciton returns the data that hadn't be updated, I need to refresh the page maybe a couple of times to get the updated data(refresh() runs everytime when created in member_management.vue)
Theoretically, the ToggleAcc function updates the data, the refresh() function gets the updated data, and I tested a couple of times to make sure the order of executions of the functions are right.
However, the situation never changes. Any help is appreciated!
The code ignores promise control flow. All promises that are supposed to be awited, should be chained. When used inside functions, promises should be returned for further chaining.
It is:
refresh:function(){
return this.$store.dispatch('member/getAll',this.displayAPI)
.then(() => {
this.AllDatas = this.$store.getters['member/getTableData'];
});
}
and
getAll:function(context,apiPath){
return axios.post(...)
...

Laravel 5.5 + Vue.js 2.x Proper API requests

I am working locally on a Laravel 5.5 project which uses Vue.js 2.5.9 on with XAMP Server.
I have to load some information to the DOM and refresh it when click "Refresh" button.
Sometimes the information is loaded and well displayed but sometimes they are not (some of the responses are):
Error 429: { "message": "Too Many Attempts." }
Error 500: { "message": "Server Error." }
I managed to "solve" the first issue (error 429) by increasing the Middleware throttle in Kernel.php from 'throttle:60,1', to 100,1)
But the second error I am not sure why I am get it sometimes and sometimes not.
I have this in my APIController (for example):
public function users()
{
$users = User::all();
return response()->json($users);
}
Then in app.js I call the methods in the created hook like this:
const app = new Vue({
el: '#app',
data: {
...
totalUsers: 0,
...
},
created: function() {
...
this.loadUsers();
...
},
methods: {
...
loadUsers: function() {
axios.get('/api/admin/users')
.then(function (response) {
app.totalUsers = response.data.length;
});
},
refreshData: function() {
this.loadUsers():
},
...
}
});
Maybe should I replace $users = User::all() to $users = User::count() to avoid loading "too much data" in API requests?
I think you should be using mounted() instead of created() in your vue.
const app = new Vue({
el: '#app',
data: {
...
totalUsers: 0,
...
},
mounted: function() {
...
this.loadUsers();
...
},
methods: {
...
loadUsers: function() {
axios.get('/api/admin/users')
.then(function (response) {
app.totalUsers = response.data.length;
});
},
refreshData: function() {
this.loadUsers():
},
...
}
});
that's the equivalent of the $(document).on(ready) in jQuery. Thats the method that fires when the window has fully loaded.
On a side note, Laravel knows when it is returning json as an ajax response, so you could probably just amend you controller method to this
public function users()
{
return User::all();
}

React throwing error: Cannot read property 'map' of undefined

I am learning React. I am following a chapter in book where they load the data from API under componentDidMount and update the state of the component as
getInitialState: function () {
return {changeSets: []};
},
mapOpenLibraryDataToChangeSet : function (data) {
return data.map(function (change, index) {
return {
"when":jQuery.timeago(change.timestamp),
"who": change.author.key,
"description": change.comment
}
});
},
componentDidMount: function () {
$.ajax({
url: 'http://openlibrary.org/recentchanges.json?limit=10',
context: this,
dataType: 'json',
type: 'GET'
}).done(function (data) {
// console.log(data);
var changeSets = this.mapOpenLibraryDataToChangeSet(data);
console.log("changeSets:" + JSON.stringify(changeSets));
this.setState({changeSets: changeSets});
});
},
When I run this, I see error on console as
"TypeError: Cannot read property 'map' of undefined
at t.render (mikobuf.js:55:41)
at _renderValidatedComponentWithoutOwnerOrContext (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:17508)
at _renderValidatedComponent (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:17644)
at performInitialMount (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:13421)
at mountComponent (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:12467)
at Object.mountComponent (https://npmcdn.com/react#15.3.1/dist/react.min.js:15:2892)
at h.mountChildren (https://npmcdn.com/react#15.3.1/dist/react.min.js:14:26368)
at h._createInitialChildren (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:26619)
at h.mountComponent (https://npmcdn.com/react#15.3.1/dist/react.min.js:13:24771)
at Object.mountComponent (https://npmcdn.com/react#15.3.1/dist/react.min.js:15:2892)"
The running link is http://jsbin.com/mikobuf/edit?js,console,output
What am I doing wrong?
UPDATE
When I added the changeSets={data} while rendering the app, I see data in console
ReactDOM.render(<App headings = {headings} changeSets={data}/>, document.getElementById("container"))
But I want the data to be pulled from API. So as soon as I remove the changeSets={data} when rendering, it fails
ReactDOM.render(<App headings = {headings}/>, document.getElementById("container"))
You are trying to use the props changeSets when it is actually part of Apps state.
This:
<RecentChangesTable.Rows changeSets={this.props.changeSets} />
Should Be:
<RecentChangesTable.Rows changeSets={this.state.changeSets} />
http://jsbin.com/tuqeciyere/1/edit?js,console,output

Meteor fetch on client undefined outside of helper

I am trying to fetch an entry in a collection with:
client/views/home.js:
criticalCrewNumber = ConfigValues.find({
name: 'criticalCrewNumber'
}).fetch()[0].value;
But I'm getting error:
Uncaught TypeError: Cannot read property 'value' of undefined
If I run the code in the browser console, the desired value is returned as a string.
I have tried various things, e.g. using findOne; placing the code elsewhere in the app; using iron-router waitOn for the subscription to come, etc. Every attempt so far has failed as I end up with undefined.
Here's how the collection is defined, published and subscribed to:
lib/config/admin_config.js:
ConfigValues = new Mongo.Collection("configValues");
ConfigValues.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Name",
max: 200
},
value: {
type: String,
label: "Value",
max: 200
}
}));
both/collections/eventsCollection.js:
if (Meteor.isClient) {
Meteor.subscribe('events');
Meteor.subscribe('config');
};
server/lib/collections.js
```
Meteor.publish('events', function () {
return Events.find();
});
Meteor.publish('config', function () {
return ConfigValues.find();
});
```
Does anyone know what's going on? Thanks.
Consider using ReactiveVar (and Meteor.subscribe callbacks):
criticalCrewNumber = new ReactiveVar();
Meteor.subscribe('config', {
onReady: function () {
var config = ConfigValues.findOne({name: 'criticalCrewNumber'});
if (config) {
criticalCrewNumber.set(config.value);
} else {
console.error('No config value.');
}
},
onStop: function (error) {
if (error) {
console.error(error);
}
}
});

react.js - Deep Object in state with async data does not work

I've just figured out that object in React's state that have multiple children cannot be rendered easily.
In my example I have component which speaks with third-party API through AJAX:
var Component = React.createClass({
getInitialState: function () {
return {data: {}};
},
loadTrackData: function () {
api.getDataById(1566285, function (data) {
this.setState({data: data});
}.bind(this));
},
componentDidMount: function () {
this.loadTrackData();
},
render: function () {
return (
<div>
<h2>{this.state.data.metadata.title}</h2>
</div>
);
}
});
The problem is that {this.state.data.metadata} renders fine..
But {this.state.data.metadata.title} throws error Uncaught TypeError: Cannot read property 'title' of undefined!
What is the proper way to deal with such async data?
I always like to add the loading spinner or indicator if the page has async operation. I would do this
var Component = React.createClass({
getInitialState: function () {
return {data: null};
},
loadTrackData: function () {
api.getDataById(1566285, function (data) {
this.setState({data: data});
}.bind(this));
},
componentDidMount: function () {
this.loadTrackData();
},
render: function () {
var content = this.state.data ? <h2>{this.state.data.metadata.title}</h2> : <LoadingIndicator />;
return (
<div>
{content}
</div>
);
}
});
with the loading indicator basically it improve the user experience and won't get much of unwanted surprise. u can create your own loading indicator component with lots of choices here http://loading.io/
this.state.data.metadata is undefined until loading occurs. Accessing any property on undefined gives you a TypeError. This is not specific to React—it's just how JavaScript object references work.
I suggest you use { data: null } in initial state and return something else from render with a condition like if (!this.state.data).

Categories

Resources