Reusable function for database access - react-native

I am currently discovering and learning to dev an app using react native
I don't have a lot of background regarding JS/React etc (more used to C,java, objC,swift etc)
So I am converting a learning app i made in swift in RN. I used the mobile database realm. I have the habit to create a singleton classe to access some method I am using in different places.
here is how I am doing it in RN
I got a js file RealmApi like that
let realm = new Realm({
path : "Pleload.realm",
readOnly : true,
schema : [Data, SUBDATA]
});
with let say 2 methods I am exporting because I was not able to export the realm var (i did not create a class)
module.exports = {
fetchData(){..... return something}
fetchSubData(param){.... return something}
}
that I am using like this in a list view
import RealmAPI from './RealmAPI'
.....
componentWillMount(){
this.setState({
dataSource:this.state.dataSource.cloneWithRows(RealmApi.fetchSbuData(this.props.section.code)),
})
It is working, but I got the feeling it is not the good way of doing it.I am style thinking in object way (java etc)
What would be the "correct" way of doing it ? Should I create the realm in each component and duplicating the method ? (that why I am trying to avoid)
thanks

You should just be able to export realm var. The syntax is as below
let realm = new Realm({
path : "Pleload.realm",
readOnly : true,
schema : [Data, SUBDATA]
});
export default realm;
and use it as below
import MyRealm from '<file path to the above code>

Related

Where do I execute native SQL queries in Loopback 4?

I'm new to Loopback 4 and I've been trying to execute a native SQL query. I found how to do it, the thing is that don't have any clue of WHERE to put it in my code in order for it to work... here's the documentation I found.
I need to know where should I put this:
const result = await repository.execute('SELECT * FROM Products');
in my Loopback project, which has many files. My goal is to make a REST endpoint like /products/[name] with [name] being a parameter inserted dynamically to the SQL query.
You can do it in your controller class as per loopback docs https://loopback.io/doc/en/lb4/Controller.html. As you will define the REST endpoint in the controller itself you can also do the insertion there using repository.execute() e.g.
#get('/products/{name}')
async doSomething(
#param.path.string('name') name: string,
): Promise<Product> {
const sql = `SELECT * FROM some_table WHERE some_field="${name}"`;
await this.productRepository.execute(sql)
--- other lines of code & return value --
}
Personally, I would implement it as a new Repository method.
Let's say your model is called Product, then you should have src/repositories/product.repository.ts file exporting ProductRepository class already present in your project. (You can run lb4 repository to create it.)
export class Product extends DefaultCrudRepository<
Product,
typeof Product,
Product Relations
> {
constructor(#inject('datasources.db') dataSource: DbDataSource) {
super(Product, dataSource);
}
// your custom method
async selectByName(name: string): Promise<Product[]> {
const rawItems = await repository.execute('SELECT * FROM Products');
// would you like to convert raw data into Product instances?
return rawItems.map(it => new Product(it));
}
}
Then you can call this new custom repository method from your controller in the same way as you would call e.g. repository.find(filter).

vuex-persistedstate not saving class methods

I'd like to preference this by saying my backgrounds in in C# so I like declaring methods within my classes. I've created a user class that contains properties and methods and I've added this to my vuex-persistedstate. One of the methods is a logout() method which clears out the properties. When I tried to invoke this method I got the following error:
TypeError: this.$data.user.logout is not a function
I then reviewed local storage and noted the user did not have reference to the class method. So I went ahead and copied the logic from the method into my vue component and it worked so I'm assuming the issue is vuex-persistedstate does not save references to methods which is why the method call did not work.
I'd like to declare the logout method in one location rather than spreading it out across vue components, what is the best practice for accomplishing this? Is it possible to do this in the class declaration or do I need a user helper file?
Sure Berco! My code is also up on GitHub so you can review it there too, but basically it seems to me that vuex does not store methods. The first file you should review is my user.js file:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/models/user.js
In this file I have a method called shallow clone which takes the info received from the API and assigns it to the user:
shallowClone(data) {
if (data !== undefined) {
this.id = data.id;
this.userName = data.userName;
this.firstName = data.firstName;
this.lastName = data.lastName;
this.nickName = data.nickName;
this.fullName = data.fullName;
this.email = data.email;
this.isActive = data.isActive;
this.isAdmin = data.isAdmin
this.isSuperUser = data.isSuperUser;
this.dateCreated = data.dateCreated;
this.dateUpdated = data.dateUpdated;
this.isLoggedIn = data.isLoggedIn;
}
}
You of course don't need to abstract this away but I've found it makes the code easier to maintain.
Then in the mounted() lifecycle hook I assign the user received from the API to the component user via the shallowClone method. Please bear in mind I've done additional work on this project and the login form is now it's own component which receives the user as a prop from the app:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/components/LoginForm.vue
mounted() {
let self = this;
window.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
self.authenticate();
}
});
this.$data.user = new User();
this.$data.user.shallowClone(this.$props.userForAuthentication);
},
The full code can be reviewed here:
https://github.com/Joseph-Anthony-King/SudokuCollective
I found a solution... I'm working on improving it. Basically I use the values pulled from localstorage into vuex to create a new user object in the vue component that has reference to the methods located in my user class declaration. I recalled recommendations that we should create clones of objects pulled from vuex for use within the vue component. I'm still refining the code but that's basic idea.

Where to setup an API in Vue.js

I need to use an API that requires initialization with an API key and some other details within my Vue.js app.
var client = api_name('app_id', 'api_key', ...)
I would need to make several API calls with the client object in multiple components in my app
client.api_function(...)
How can I avoid repeating the initialization step in every component?
I'm thinking about using a global mixin in main.js for that
Vue.mixin({
data: function() {
return {
get client() {
return api_name('app_id', 'api_key');
}
}
}
})
Is this a good approach?
I'd rather move your getter to a service and just import, where you actually need it. It doesn't seem to fit into data section, more like methods. A mixin is a decent approach if you need lots of similar stuff: variables, methods, hooks etc. Creating a mixin for only 1 method looks like overkill to me.
// helper.js
export function getClient () {
// do stuff
}
// MyComponent.vue
import { getClient } from 'helpers/helper`
// Vue instance
methods: {
getClient
}
How about creating a helper file and writing a plugin that exposes your api url's? You can then create prototypes on the vue instance. Here's an example,
const helper = install(Vue){
const VueInstance = vue
VueInstance.prototype.$login = `${baseURL}/login`
}
export default helper
This way you can access url's globally using this.$login. Please note $ is a convention to avoid naming conflicts and easy to remember that it is a plugin.

How do you store a non mobx-state-tree type (Class instance) in models?

I get:
Error: [mobx-state-tree] expected a mobx-state-tree type as first
argument, got class HubConnection {
constructor(urlOrConnection, options = {}) {
options = options || {};
When trying to do this:
import { HubConnection } from '#aspnet/signalr-client';
.model('MyStore', {
connection: types.optional(HubConnection, new HubConnection('http://localhost:5000/myhub')),
})
I could declare it in the constructor of my React component instead as I used to
constructor(props){
super(props);
this.connection = new HubConnection('http://localhost:5000/myhub');
}
but then all attached eventhandlers also needs to be defined in the component
componentDidMount(){
this.connection.on('Someaction', async(res: any) => {});
}
and starting / closing of the connection
handleBtnClicked = () => {
this.connection.start().then(() => self.connection.invoke('Someotheraction'));
}
and ideally I think this belongs in the model and model actions, so the react component is only triggering actions on the model and nothing more.
Is there a way to store other than mobx-state-tree types in mobx-state-tree models, can you somehow wrap it in a mobx type or is this actually not something that belongs in mobx and therefore intentionally.
It is intentional that mobx-state-tree models can only define properties of MST based types. This is because those types are snapshottable, serializable, patchable etc. While something like a HubConnection is not a thing that could be snapshotted, rehydrated etc.
It is possible to store arbitrarily things in a MST tree, but just not as props. Instead, you could use volatile state

calling method from external file in express routes

Hi I am new to expressjs. I have an admin route where I would like admin to update record and etc. I don't want to write code to updated record under the route rather I just to pass some functions or object that fetch records from db or updated them. I am using passportjs for authenticate. Currently my route look like this -
app.get('/admin', function(req, res){
res.render('admin', {
title: "Welcome Member_name ",
user: req.user
});
});
So I have created another js file for all admin operation. its under root/controller/admin.js and its looks like this -
var mysql = require('mysql'),
dbconfig = require('../config/database'),
connection = mysql.createConnection(dbconfig.connection);
module.exports = {
}
what I am after is to write some function that will get some data from the database and return the object so that I can pass the object to my route and from there to the view. Can anyone help me plz? thanks. Also if you know best practice for learning expressjs plz let me know. Thanks a lot in advance. Cheers.
I'll try to answer this one for you, although you question was a bit muddy to understand. If I'm right you'd like to call a method in your module from your route?
Let us say your module file was called admin.js for the following example. This is how you would create a method accessible outside of the module.
admin.js
var mysql = require('mysql'),
dbconfig = require('../config/database'),
connection = mysql.createConnection(dbconfig.connection);
module.exports = {};
module.exports.retrieveData = function() {
//Data retrieval code here.
};
Then in your routes file, let us say routes.js for the example. This is how you would call the method.
routes.js
var admin = require('./admin.js') //Remembering to require the module!
database.retrieveData();
You would then pass your query through a parameter in the retrieveData() method.