calling another function in the default function - javascript

I am using react and I created a auth file to store all of my api request related to authentication purposes. I have inside a default function signin with a signin request, and I also want to store a signup request in the same file. I believe I am doing something wrong as it is not rendering properly.
here is my code:
import React from 'react'
import axios from 'axios';
export const signin = async(data)=>{
const config = {
headers: {
'Content-Type': 'application/json'
},
};
const response = await axios.post('http://localhost:5000/api/auth/signin', data, config);
return response;
};
const signup = async(data)=>{
const config = {
headers: {
'Content-Type': 'application/json'
},
};
const rep = await axios.post('http://localhost:5000/api/auth/signup', data, config);
return rep;
};
export default signin;

Like #saeed stated in his comment, you could export both signin and signup normally and import them somewhere else using import {signin, signup} from 'access'.
import React from 'react';
import axios from 'axios';
export const signin = async (data) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const response = await axios.post(
'http://localhost:5000/api/auth/signin',
data,
config,
);
return response;
};
export const signup = async (data) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const rep = await axios.post(
'http://localhost:5000/api/auth/signup',
data,
config,
);
return rep;
};
And to import the functions:
import {signin, signup} from 'somefile'

Related

How to use getServerSideProps method

I'm trying to make my page SEO friendly by using getServerSideProps method. I have tried to google it but cannot find any specifc example for my case. I'm not sure how to do it. I have a useEffect method currently.
import Header from './Header.js';
import Footer from './Footer.js';
import React, { Component, useState, useEffect } from 'react';
import Link from 'next/link';
import { useParallax, ParallaxBanner } from "react-scroll-parallax";
import { useTranslation } from "react-i18next";
import axios from "axios";
//import { Link, useLocation } from 'react-router-dom';
import Post from "./Post";
function Article({postSlug}) {
const { t, i18n } = useTranslation();
const [post, setPost] = useState([]);
const [posts, setPosts] = useState([]);
const currentlocale = typeof window !== 'undefined' ? localStorage.getItem('locale') : null;
useEffect(() => {
if(postSlug){
axios({
method: "POST",
url: process.env.NEXT_PUBLIC_API_URL + '/pages/article',
headers: { 'Content-Type': 'application/json;charset=UTF-8', "Access-Control-Allow-Origin": "*", "Accept": "application/json" },
data: {
country: currentlocale,
slug: postSlug
}
}).then(result => {
setPost(result.data.json.article);
setPosts(result.data.json.articles);
});
}
}, [postSlug])
return (
<div id="web-front">
<Header />
{post.title}
<Footer />
</div>
)
}
export default Article;
getServerSideProps only runs on routes / files created inside /pages folder.
Move your data fetching methods from the component to the getServerSideProps function.
You can get postSlug from the context.req[1] object getServerSideProps receives.
LocalStorage won't be available on server. Instead use cookies as a replacement for localStorage, since cookies is available on the context.req object. [2]
function Article({ initialPost, initialPosts }) { //👈 received from ssr props
const { t, i18n } = useTranslation();
const [post, setPost] = useState(initialPost); // set initially
const [posts, setPosts] = useState(initialPosts); // set initially
return (
<div id="web-front">
<Header />
{post.title}
<Footer />
</div>
);
}
export async function getServerSideProps(ctx) {
const postSlug = ctx.req.params.postSlug; // 👈 handled by you
const currentLocale = getCurrentLocaleFromCookies(ctx.req); // 👈 handled by you
let initialData = {};
try {
initialData = await axios({
method: 'POST',
url: process.env.NEXT_PUBLIC_API_URL + '/pages/article',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Allow-Origin': '*',
Accept: 'application/json',
},
data: {
country: currentlocale,
slug: postSlug,
},
});
} catch (err) {
console.error(err);
}
return {
props: {
initialPost: initialData.data.json.article,
initialPosts: initialData.data.json.articles,
},
};
}
export default Article;
Reference:
https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props
https://stackoverflow.com/a/63875689/7679903

React router have issues on action in children routes react-router-dom#v6

I have little environment in nodejs with mongodb and express-session, i follow react router tutorial https://reactrouter.com/en/main/start/tutorial , and it's fine. But when i decide to make two children from layour route with two different actions like register and login on different submit the same action is throw. I can't find anything to solve it. Why on different action children my app read the same action for both?
APP.JSX FILE
import './App.css';
import React, { useState } from 'react';
import {
createBrowserRouter,
RouterProvider,
Route,
} from "react-router-dom";
import Register, { registerAction } from './component/Register';
import Login, { loginRequest } from './component/Login';
import Simplejs, {loader as isAuthLoader } from './component/SimpleJs';
import Layout from './component/Layout';
import ErrorPage from './component/ErrorLayout';
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
errorElement: <ErrorPage />,
children: [
{
path:"",
element: <Login />,
action: loginRequest,
},
{
path: "",
element: <Register />,
action: registerAction,
},
]
},{
path:"/index",
element: <Simplejs />,
errorElement: <ErrorPage />,
loader: isAuthLoader,
children: [
]
}
], {basename: "/"});
function App() {
return (
<section>
<RouterProvider router={router} />
</section>
);
}
REGISTER ACTION:
export async function registerAction({ request }){
const formData = await request.formData();
const updates = Object.fromEntries(formData);
await Registration(updates);
}
REGISTRATION HANDLER:
export const Registration = async (object) => {
console.log('Registration');
const config = {
headers: {
'Content-Type': 'application/json'
},
withCredentials: true,
credentials: 'include'
}
const body= object;
try {
const res = await axios.post('/registration', body, config)
console.log(res);
const data = res.data
if(data) return {data}
} catch (error) {
if(error.response.data.msg){
console.log(error.response.data.msg);
}else if(error){
console.log(error)
}else{
console.log('errore');
console.log(error);
}
}
}
LOGIN ACTION:
export async function loginRequest({ request }){
const formData = await request.formData();
const updates = Object.fromEntries(formData);
await LoginAccess(updates);
}
LOGIN HANDLER:
export const LoginAccess = async (object) => {
console.log('Login');
const config = {
headers: {
'Content-Type': 'application/json'
},
withCredentials: true,
credentials: 'include'
}
const body= object;
try {
const res = await axios.post('/login', body, config)
console.log(res);
const data = res.data
if(data) return {data}
} catch (error) {
if(error.response.data.msg){
console.log(error.response.data.msg);
}else if(error){
console.log(error)
}else{
console.log('errore');
console.log(error);
}
}
}

Making axios global in Vue project is not working

Until now, I had been importing axios in each Vue component where I wanted to make HTTP requests, like this.
<script lang="ts">
import axios from 'axios';
#Component
export default class ExamplePage extends Vue {
created(): void {
axios.post(some_path);
}
}
However, now I want to define a global interceptor for all axios requests, basically to catch all 401 unauthorized responses from the backend server (Rails) and log out the user.
My understanding so far is that you must instantiate axios once and use it everywhere, instead of importing and using a different instance in each file.
I've referred to this and this, and tried the below.
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
document.addEventListener('DOMContentLoaded', () => {
new Vue({
el: '#application',
router,
render: (h) => h(App),
});
});
axios.interceptors.response.use(
response => response,
error => {
const status = error.response;
if(status === 401) {
// do stuff
}
}
);
Vue.prototype.$http = axios
When I tried to call this.$http.put(...) in another file, it said property $http doesn't exist (I'm guessing it's because this in the context of that component is the component itself, but I'm not sure). How can I fix this?
[UPDATE] Thanks to the responses, I decided to initialize an axios instance in a separate file and then use that instead. However, this is still not working. The 401 responses don't seem to be triggering the interceptor at all.
Is there some additional configuration necessary?
// axios-instance.ts
import axios, { AxiosInstance } from 'axios';
const axiosInstance: AxiosInstance = axios.create();
axiosInstance.interceptors.response.use(
response => response.data,
async function(error) {
console.log("THIS IS THE 401 INTERCEPTOR")
const status = error.response;
if(status === 401) {
// Log out user
}
}
);
export default axiosInstance;
// Some component
<script lang="ts">
import axiosInstance from 'axios-instance';
#Component
export default class ExamplePage extends Vue {
created(): void {
axiosInstance.post(some_path);
}
}
Doesn't solve your question directly, but the way I create instance of axios is:
// axios-instance.js
import axios from 'axios'
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance
After you just import the instance
// application.js
import axios from '../../axios-instance'
You can't use this when you aren't in the vue instance.
Try this:
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
axios.interceptors.response.use(
response => response,
error => {
const status = error.response;
if(status === 401) {
// do stuff
}
}
}
);
Vue.prototype.$http = axios;
const VueInstance = new Vue({
el: '#application',
router,
render: (h) => h(App),
});
Now you can make HTTP request using this.$http:
<script>
export default {
methods: {
doStuff() {
this.$http.post('path_to_post_request').then(({ data }) => {
// do something with received data
}).catch((e) => {});
}
}
}
</script>
I had the same problem.
It is not so clear in Axios API docs that error responses should be intercepted in the response interceptor's error callback.
It should be done like this:
axios.interceptors.response.use(function (response) {
//This is the success callback in case u ever need it
return response;
}, function (error) {
// This is the callback I was talking about.
// Do something with request error
// Tip: error.response is the actual response with error code
return Promise.reject(error);
})
This can be seen in the Axios API Documentation - Interceptors section
I recommend that you implement the axios instance in a separate js file:
// utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: '',
headers: {},
withCredentials: true,
// ...other options
})
// request interceptor
service.interceptors.request.use(config => {
// ...
return config
}, err => {
return Promise.reject(err)
})
// response interceptor
service.interceptors.response.use(response => {
// ...
return response
}, err => {
return Promise.reject(err)
})
export default service
And then you can using http request like this:
import request from '#/utils/request'
request({
url: '',
method: 'post',
data: {}
}).then(res => {
// Do something after the request is successful
}).catch(err => {
// Do something after the request fails
})
Try implementing a service:
src / services / yourservice.js
import axios from 'axios'
const apiClient = axios.create({
baseURL: 'https://example.com/api',
withCredentials: false,
timeout: 1000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa('api_username_here' + ':' + 'api_password_here')
}
})
export default {
getOrders(){
return apiClient.get('/orders?status=processing')
},
getProducts(id){
return apiClient.get('/products/' + id)
},
}
Use the service in a Component:
src / component / yourcomponent.vue
import YourService from '#/services/YourService.js';
data() {
return {
orders: null, //Typescript
}
},
created() {
yourservice.getOrder(id).then(response => {
this.orders = response.data
}).catch(error => {
console.log(error)
});
}

Custom Middleware error even after implemented

I am using API call via Async-Await that requires a custom middleware, I am using Thunk as custom Middleware. All dependencies are installed. Then also, somehow it fails to detect the middleware or something like that.
My code when executed shows the following error:
This is my Actions Page: I used Async-Await which led me to this error
import axios from "axios";
export const saveTwitterToken = (token) => {
return ({
type: TWITTER_OAUTH,
payload: token
});
};
export const callTwitterAPI = async (config) => {
const request = await axios({
"url": "https://api.twitter.com/1.1/statuses/home_timeline.json",
"method": "GET",
"headers": {
"Authorization": " _Something_ "
}
});
return ({
type: "api",
payload: request
})
};
This is my Index.js Page:
import React from "react";
import ReactDOM from "react-dom";
import App from './App'
import {Provider} from "react-redux";
import 'bootstrap/dist/css/bootstrap.css';
import stores from "./utils/store";
ReactDOM.render(
<Provider store={stores}>
<App/>
</Provider>
, document.getElementById('root'));
This is the Custom Middleware Store File:
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from '../reducers';
const store = createStore(
reducers,
{},
compose(
applyMiddleware(thunk)
)
);
export default store;
You've to use dispatch for Asynchronous Redux Action as follow:
export const callTwitterAPI = config => async dispatch => {
const request = await axios({
"url": "https://api.twitter.com/1.1/statuses/home_timeline.json",
"method": "GET",
"headers": {
"Authorization": " _Something_ "
}
});
dispatch({
type: "api",
payload: request
})
}
More better way is to use promise as follow:
export const callTwitterAPI = config => dispatch => {
axios({
"url": "https://api.twitter.com/1.1/statuses/home_timeline.json",
"method": "GET",
"headers": {
"Authorization": " _Something_ "
}
}).then(request =>
dispatch({
type: "api",
payload: request
})
).catch(error => handle it OR dispatch another action)
}
I hope it help you.

How to access Vuex store in helper functions?

For vue-axios auth by api_token i use helper file api.js.
i got error - Uncaught TypeError: Cannot read property 'getters' of undefined.
I think api.js helper does not see global storage - Vuex $store.
In other components i do not need import Vuex storage, he avalaible in any place of app.
How use this.$storage in helper?
//api.js
import axios from 'axios'
let api_token = this.$store.getters.get_api_token //got error!
export function get(url) {
return axios({
method: 'GET',
url: url,
headers: {
'Authorization': `Bearer ${api_token}`
}
})
}
//Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
api_token: 'vnbnvnvnvb',
},
getters: {
get_api_token(state){
return state.api_token
}
},
});
export default store
//App.vue
import {get} from './helpers/api';
export default {
created() {
get(`/api/user/${1}`)
.then((res) => {
///do it
})
.catch((err) => {
console.log(err);
})
}
}
Found answer
// some JS file
import store from './../store'; // path to your Vuex store
let user = store.getters.user;
// do stuff with user
https://laracasts.com/discuss/channels/vue/vuex-accessing-vuex-outside-of-a-vue-component

Categories