Problem
Hello to all,
Given the example code:
<Table
data1={data}
data2={columns}
/>
I've to pass data.property to columns,
I will get data.property after a successful call to a remote server, so initially data will be simply null.
I've the data inside columns displaying in this way:
const columns = [
function() {data.property ? doThis : doThat },
{object1},
{object2},
{object3},
....
]
Consideration
I cannot change the order or the dimension of the column, so I cannot merge the two objects and the const columns is in another file than the starting table.
We are using ReactTable.
Why do I need the property of Data?
I need it to do a check inside the function inside columns,
something like this:
data.property.length ? DoThis : DoThat
My Tries
I tried to merge the two object in a new one, but I messed up everything and broke my table.
By the nature of your question, it appears you require to use onFetchData() to ensure all data is present before rendering the view.
An example of this type of usage is detailed within the npm documentation usage examples for the react-table project
This is the preferred method, I am familiar with the concept writing APIs in Express, where it is required that you use the async package along with a series of functions in order to ensure all data has been generated before the callback provides the data to your view being rendered.
Hopefully this fishing rod helps you in the right direction!
If this suggestion helps you, please do edit your question and share the solution you have written to tackle the issue so future viewers of this question can also benefit.
Not sure if I understand your question correctly, but I can imagine that your code crashes due to either data or data.property being undefined, as it is still waiting for your asynchronous API call to finish.
In order to prevent this you could do the following:
( data && data.property && data.property.length ) ? DoThis : DoThat
Related
Im doing a project where i call one api, this given API service will handle all the given data and split it to different collections.
Given example
service.js
async function create(params, origin) {
const { param1 , param2 , param3 } = params
const collection1 = new db.Collection1(param1)
await collection1.save()
const collection2 = new db.Collection2(param2)
await collection2.save()
const collection3 = new db.Collection3(param3)
await collection3.save()
}
My questions are:
What is the best practice? Should I create a general model schema that groups all the collections with the parameters, "param1,param2,param3", and insert it in the collection then call another function that splits all the values into Collection1,Collection2....
How can i handle if one collection insert throws an error, to delete all the previously inserted collections ? For example the values of param2 is not valid, but param1 and param3 are, how can i handle to delete the collection 1 and 3 and throw an error ? Whats the best way to achieve this?
Generally all the above examples are simplified, we are talking about at least more than 10 collections and more than 15 parameters.
Basically you are talking about having multiple route handlers for a single path.
Generally you should handle server-side validation & sanitation on the input data before inserting into the db and throw errors right away if rules don't match, so having to delete previous 2 collection inserts in case the 3rd one fails is not needed anymore.
Check out express-validator middleware for this aspect.
Ideally you should have one route handler per path for several reasons but I think the most common one is ease of maintenance and debugging(conceptually like separation of concerns). It's easier to execute a sequence of requests to different paths and eventually await the response from the first request to be used in the next request and so on(if that's the case). In my opinion you're just adding a layer of complexity not needed.
It might work if you develop alone as a full-stack, but if you have a team where you do the back-end and somebody else does the requests from the front-end and he encounters a problem it'll be much harder for him to tell you which path => handler failed, because you're basically hiding multiple handlers into a single one path => [handler1, halder2, handler3]. If you think about it, this behaviour is causing your second question.
Another thing is, what do you do if somebody needs to operate just a single insert from that array of inserts you're trying to do? You'll probably end up creating separate paths/routes meaning you are copying existing code.
I think it's better for chaining/sequencing different request from the front-end. It's much better and elegant, follows DRY, validation and sanitation is indeed easier to code and it gives the consumer of your api freedom of composition.
Ive looked related posts and couldn't quite find what I was looking for.
So I am build a backend rest api and I have certain tests I am collecting data on. The tests have their own models, and these models are associated with collections (obviously).
So I have a separate controller for each model. Now I have a "job" controller which queries data from each separate test. Now I have a separate script where I store these model objects in an JSON object. I am wondering how I can access these models properly (I am close but cant quite assign properly). Here is the block:
const testMappings = {
'aprobe':aprobe,
'status':status,
//'rxserial':rxserial,
}
Now when I try assignment as follows, where testMappings is the imported script variable:
const testMappings = activeTests.testMappings;
console.log(testMappings['aprobe']);
I get the following output:
Model {aprobe}
I would like to access the actual aprobe object. Also if anyone knows a better way of dynamically assigning these (instead of having bunch of if statements ie if(name == 'aprobe').... do something), it would be much appreciated.
You are probably looking for something like below :
const name = 'aprobe';
Object.keys(testMappings).indexOf(name) > -1 ? testMappings[name] : null
the above should give you: Model {aprobe}
So basically if the key exists in your object then you'd like to fetch the value of that key which would give you your model dynamically.
I want to serialize my Sounds model for use in my game.js file. This is what I have.
views.py
def index(request):
context = {'sounds': serializers.serialize('json', Sounds.objects.all()) }
return render(request, 'index.html', context)
index.html
<button type="submit" onclick="main()">Let's Start!</button>
game.js
function main(){
var data = {{ context|safe }};
// print all objects here
}
It's not working - not sure what the issue is. Basically, when I click the button in index.html, it should go to the main function (this part works), and then set a variable data with the objects in the model so that I can use it. Also, is it possible to filter objects in data so that I have a list with only the objects with id = 1? I want to do this in game.js (not in views.py or elsewhere).
It's hard to tell what the exact problem with the serialiser is without an actual error log. If you can actually open the console that django is running in, it should display the error when it occurs. From that a better diagnostic of the issue can be made. It would be wise to do this in the future otherwise questions like this will be downvoted.
Yes, you can filter arrays in Javascript using the filter function. The function creates a new array by interating through the objects in the array that will be passed into a function, which should return true if it should exist in the new array or false it is shouldn't.
So for the example you provided, it would appear as so:
sounds = sounds.filter((sound) => { sound.id === 1; });
Note you will have to assign the new array, the original array will not change bu running the function itself.
I highly recommend you search for solutions to these problems yourself before creating threads on Slack Overflow or your reputation will quickly decrease.
I am making a project with Meteor and I'm having some issues trying to get data out of mongodb in JavaScript. I have the following in a function:
console.log(Time.find({today: "Saturday"}).fetch());
In my publish.js file on the server side I have the following:
Meteor.publish("time", function () {
var currentUserId = this.userId;
return Time.find({user: currentUserId});
});
And In my subscriptions file I have the following:
Meteor.subscribe("time");
This function gets called later down in the code but it returns an empty array. If I run this code in my browsers console it returns an array with 2 objects in it, which is correct. This leads me wondering if I can use the .fetch() function from within my code? As if I leave off the .fetch() it returns what looks like the usual giant object. My real problem is I need the data in the form that .fetch() gives it to me in. I think it's because the function gets triggered before the data gets a chance to load in, as if I switch out the .fetch() for a .count() it returns 0.
Is there any way around this or a fix?
Where are you you running that console.log?
There are a couple fundementals here that I believe you may have glossed over.
1 Pub / Sub
This is how we get data from the server, when we subscribe to a publication i becomes active and begins to send data, this is neither instant or synchronous, (think of it more like turning on a hose pipe), so when you run your console.log, you may not yet have the data on the client.
2 Reactive contexts
One of the fundamental aspects to building anything in meteor is its reactivity. and it helps to start thinking in terms of reactive and non reactive contexts. A reactive context is one that re-runs each time the data it depends on changes. Using an autorun (Tracker.autorun or this.autorun insdie a template lifecycle callback) or a template helper are good examples. By placing it in a template helper it will re-run when the data is available.
Template.Whatever.helpers({
items: function() {
// ...do your find here.....
}
});
As items is a reactive context, depending on the collection data, it re-run when that changes, giving you access to the data when the client has them.
3 Retrieving Non Reactive Data
Alternatively it is also possible to retrieve data non-reactively by using Meteor.call with a meteor method, and then doing something with the result, in the callback to the Meteor.call. Depending on what you're doing, Meteor.wrapAsync may also be your friend here.
a simple example (out of my head, untested) :
// on the server
Meteor.methods({
gimmeStuff: function() {
return "here is your stuff kind sir!";
}
});
// on the client
Meteor.call('gimmeStuff', function(err, result) {
if (err || !result) {
console.log("there was an error or no result!");
return false;
}
console.log(result);
return result;
});
4 Its Unlikely that you actually need ithe .fetch()
If you're working with this in a template, you don't need a fetch.
If you want this to be non-reactive you don't need a fetch
As one of the commenters mentioned, a cursor is just a wrapper around that array, giving you convenient methods, and reactivity.
5 Go Back to the Begining
If you haven't already, I would highly recommend working through the tutorial on the meteor site carefully and thoroughly, as it covers all of the essentials you'll need to solve far more challenging problems than this, as well as, by way of example, teach you all of the fundamental mechanics to build great apps with Meteor.
Here's a rather standard way to set a route in Iron Router:
Router.route('/posts/:_id', {
name: 'postPage',
data: function() { return Posts.findOne({_id: this.params._id}) }
});
Experimenting around a little, beginner as I am, I tried:
Router.route('/posts/:whatever', {
name: 'postPage',
data: function() { return Posts.findOne({_id: this.params.whatever}) }
});
This works well, up to a point. True, whatever will scoop up whatever is after /posts/ as its value, and the data context will indeed be the same as before... but linking to specific posts now won't work!
So,
{{title}}
simply won't work doing it "my" way (linking to nothing at all).
I can't fully wrap my head around this, and I'm too much of a novice to grasp the source code for Iron Router, so my hope is that someone here can explain it in a manner that even a beginner like me can comprehend.
Preferably like something like this:
First {{pathFor 'postPage'}} looks inside the routes to find the one named postPage.
It sees that this route corresponds to /posts/ followed by something else.
Looking inside the data context it finds that only one post is returned, namely the one with the same _id as whatever comes after /posts/.
It understands that it should link to this post, cleverly setting the url to /posts/_id.
This is wrong, most likely, and it doesn't explain why it would work when whatever is turned into _id. But it would help me immensely to see it parsed in a similar fashion.
Edit: Cleaned up my question so it is easier to grasp.
There's a simple set of circumstances that together lead to confusion:
The Posts.findOne issue is explained by the fact that the first argument can be either a selector or a document _id. So it's not really a shortcut but rather a documented feature.
As you found, putting :something in the iron:router URL causes that value to be reported as this.params.something inside the route function. This also registers something as an parameter to that route, which brings us to how pathFor works.
The pathFor helper takes two inputs: first the name of the route (in this case 'postPage') and second an object of parameters, which can come either from the second argument as in {{pathFor 'postPage' params}} or from the data context like so: {{#with params}}{{pathFor 'postPage'}}{{/with}}.
Now, here's why passing in a document from the database works if you call the parameter _id but not if you call it whatever: the post object that you retrieved from the database _has an _id field, but it doesn't have a whatever field. So when you pass it into pathFor, it only passes along the correct _id if the parameter to the route also happens to be called _id.
Let me know if that makes sense, I agree that this is somewhat confusing and that this "shortcut" hides what exactly pathFor and params actually do.