Can I use use* functions (useState,useRef, useContext) in non rendering components? - reactjs

I would like to create a utility class for accessing my API more easily. Since the API needs credentials I need to access the global context in which user information is stored.
But this API utilities class is not a rendering component, its simply a class with functions that make calls to the API.
So can I still use all the use* functions from within the functions of this class? Or should I call useContext from within the given component function and pass the credentials to the API class?

nope, you just can use hooks in the body of your components, not in normal function/class...
pass your credentials through the parameters or get those from another module.
an example for the second case I mentioned (get credentials from another module):
import cookie from "js-cookie";
function getToken() {
return cookie.get("token");
}
function getUserPermissions(id) {
axios.get("https://blahblahblah.com/.....", {
headers: {
Authorization: `Bearer ${getToken()}`
}
})
}

Related

Fetch data from API and pass the fetched data as parameter to other API to fetch regarding data?

I am working on an app and getting all the data from API's for different components.And when calling login api I am getting the json as response with user details. I have a component which requires some of the user details to pass to another API to fetch regarding data. Currently I am fetching data of the components by passing actual user details as a parameter to the API, and I want to make it dynamic.
Where Whenever a user will logged in, other API's should dynamically take the required parameters and fetch the json data. How can I achieve this?
Create an async function that logs the user in and on the result, call the second API conditionally with the result of the login call.
async function loginUser (params){
try {
// api call here
// if everything is successful
return {
success:true,
data: userObject
}
} catch(e){
return{
success:false,
error:e
}
}
}
const result = loginUser(params)
if(result.success){
// perform another call whcich requires userObject
}

Testing authorized API calls on FrontEnd

I have a react app, in which I have defined functions for APIs, so that I can call these functions where I need.
Now the thing is I want to write tests for these API calls. My API function use Axios internally for executing requests. In the app I use Axios Interceptors to add auth token to these requests, and now I want a clean way to test such authorized APIs which needs tokens in their headers.
My question is how can I use test these authorized API function without disturbing my design.
Here is a sample API function which I want to test, it needs auth token in the header:
export const delete_store = (id) => {
return Axios.delete(`api/example/url/${id}`);
};
you can pass headers as second argument.
Axios.delete(URL, {headers: { auth: token }})

Call API resource using meteor

I would like to call an API resource using meteor and React. What I would like to happen is;
load a page
have a form shown to a user
user submits form
use the form data as parameters for the API call via POST
returns the API response to React.
How do I achieve this? Am I on the right track by using Meteor.wrapAsync?
Meteor.wrapAsync wouldn't be neccesary. If you have a button in React. You should keep the fields in the state. React Forms. Then use this code in your component to call a meteor method.
onClick(e){
e.preventDefault();
const { objectToPost } = this.state;
Meteor.call("some_method", objectToPost, (err, res) => { doSmthWithFrontend });
}
The Meteor method will be called async for you and return when the call returns. In this method you can use Meteor Http to achieve what you want.

How do I create a globally accessible variable in React JS

In my react JS app, I make many API calls,
Rather than having to specify:
const BASE_URL = 'https://apiurlgoeshere.com/'
on every page, I'd rather have BASE_URL accessible throughout the entire application, so I can just do BASE_URL + API_CALL for example
If this is just adding BASE_URL, then this can be achieved by declaring it inside a constants.js file and exporting it from there. But then, that makes us do BASE_URL + "something" each time we make a network request which isn't really ideal either. Also there might be some scenarios where other configuration have to be shared, like say, a common header that has to be added to all the requests.
To solve this, most request libraries have in-build solutions. If we are choosing axios as the most popular one, we can create a instance like:
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance;
and import this everywhere the axios is going to be used like:
import axios from "./axios-instance";
assuming axios-instance.js is the file where the instance is created. Now you can skip adding the BASE_URL to every request as it is already provided in the instance.
If webpack is being used for code bundle, DefinePlugin can be used.
new webpack.DefinePlugin({
'BASE_URL': JSON.stringify('https://apiurlgoeshere.com/')
});
For gulp build, gulp-replace can be used.
.pipe(replace('BASE_URL', 'https://apiurlgoeshere.com/'))
I know it's been a while since I created this post - just wanted to go through what I've learnt really.
It's a great way to set a global config for Axios. I typically create a folder and create an api.js file within it which I use to make all of my API calls, this is great as it means you only have to specify headers / base URL / credentials etc once.
Here is a code example for a solution:
function apiCall (method, path, data) {
let url = "https://urltoyourapis.com/";
return new Promise((resolve, reject) => {
return Axios[method](url, {headers}, data).then(res => {
return resolve(res);
}).catch(err => {
return reject(err);
})
})
}
Now, whenever you want to make an API call you'd import this function into the file where you would like to make the API call and do the following:
apiCall("get", "account-info")
This will then make an API call to the endpoint "account-info" to get the information, you can either await and set the result to a variable or use .then .catch to handle the response.

Redux dispatch inside Meteor Accounts.onEmailVerificationLink

Is there a way to use this.props.dispatch of the redux store inside Accounts.onEmailVerificationLink ?
I am using React and React-redux inside a Meteor app.
Upon email verification i would like to send data through this.props.dispatch
I'm trying to make this work(if it is even possible):
Accounts.onEmailVerificationLink(function(token, done){
console.log('onEmailVerificationLink token', token)
console.log('this',this)
var outerthis = this
Accounts.verifyEmail(token, function(error){
if(R.isNil(error)){
}else{
console.log('error of verifyEmail', error)
outerthis.props.dispatch(changemainmessage(error.reason))
}
})
done()
})
You need to import your store object from wherever it is defined
import store from '../config/store'
Then you can dispatch an action directly from the store object
store.dispatch(changemainmessage(error.reason));
Read more here
Also, I'd recommend using camelCase for your variables - it's way more readable and follows JavaScript convention
So changemainmessage() would be changeMainMessage()

Resources