I have a react project where I'm making requests to a third-party api. I created an axios file where I set a baseUrl for requests, and I export a function which will make a request to a particular endpoint.
However, when I import and execute the function in my App.js, the request is made with localhost:3000 as the base url. Can't figure out why
I made a sandbox to demonstrate
here is the code for my axios.js file
import axios from 'axios'
const instance = axios.create({
baseUrl: `https://api.-----.com/svc/topstories/v2/`
})
export const api_key = '------------------------'
export const getTopStories = async () => {
const {data: {results}} = await instance.get(`/home.json?api-key=${api_key}`)
return results
}
export default instance
You should use baseURL instead of baseUrl
Related
I have a component called Login.js There I import Axios libray normal way and it works like this.
import axios from 'axios';
const data = await axios.post('/user/login/', {
email: e.email,
password: e.password,
});
Getting 404 is fine because I didn't set any base URL for the Axios. Please note all the requests, response headers here.
Then I try to created Axios instance inside a lib folder and import it like this
/src/lib/axios.js
import axios from "axios";
const baseUrl = process.env.REACT_APP_BE_URL;
const axiosInstance = axios.create({
baseURL: baseUrl,
});
export default axiosInstance;
I import this instance instead of normal Axios import.
import axios from 'libs/axios';
Now I see the request like this a lot of properties missing in the request and this isn't working
How do I fix this?
Any help thanks in advance.
the error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'get')
the main files
the axios file
import axios from "axios";
const token = "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOJQ......";
export default axios.create({
baseURL: "https://api.themoviedb.org/3",
headers: {
authorization: `Bearer ${token}`,
},
});
the main.js file
import api from "#/data/db";
const app = createApp({});
app.config.globalProperties.$http = api;
the home file
async mounted() {
const response = await this.$http.get("/movie/550");
console.log(response);
},
Check out this sandbox. It logs a promise in the console, doesn't give the undefined error. Try putting your actual key in the db.js file and check if you can make a request to the API.
I think the problem in your code is with this line const app = createApp({});
You need to pass a component with the mounted() hook in it as an object param to the createApp function. Then you need to mount the app.
import api from "#/data/db";
import Home from "#/Home.vue";
const app = createApp(Home);
app.config.globalProperties.$http = api;
app.mount("#app"); // Provide a valid html id that exists in your index.html file
I'm searching for a clean way to store my access token in React.
First thing: I don't want to use local storage. I don't need to make my access token persistent since I can always refresh it.
I also excluded a cookie since I want to prevent CSRF attacks. By storing the access token only in memory, in fact, the page needs to be loaded to get the token and authenticate requests (refresh token can be used only to refresh)
I thought of using redux/context, however, the function calling the API is not a child of a component so I can't access the token from that. Furthermore, I don't want to pass the token as a parameter, since I want to keep decoupled the HTTP logic. Maybe there is a clean way to use it?
After a bit of research, I found that using a global variable is a working "cheat" to obtain what I want. However, I was guessing if there was a clearer way to get the same result.
//token.js
const access_token= "";
export const setAccessToken(token){
access_token=token;
}
export const getAccessToken(){
return access_token;
}
//NOTICE:
// -ON LOGIN/REFRESH: I set the access token
// -ON API CALLS: I get the access token and I add it to the header
api.js
const baseURL= "http://my_base_url";
const generateApiInterface = ()=>{
let headers : any= {
};
token=getAccessToken(); //HERE I NEED TO RETRIEVE MY ACCESS TOKEN
if(token){
headers={
'Authorization': 'Token '+ token,
...headers //append other basic proprieties
}
}
return axios.create({
baseURL: baseURL,
headers: headers
});
}
const api = generateApiInterface();
The way you're doing it is preferable to keep anything in memory. If this is server side, then you'd want to make sure you delete the token once you're done, but if not then the current approach is desirable. Note, you're using a const, you'd want to change that to a let. Another idea would be to use session storage, but then that brings the idea of XSS.
However, React provide a way to have "global" state - this would be to use a provider and context. Here's an example:
// provider.tsx
import React, { useContext, createContext, FC, useState } from 'react'
type AccessTokenContext = [string, React.Dispatch<React.SetStateAction<string>>]
const AccessTokenProvider: FC = (props) => {
const [accessToken, setAccessToken] = useState<string>(null)
return <AccessToken.Provider value={[accessToken, setAccessToken]} {...props} />
}
const AccessToken = createContext<AccessTokenContext>(null)
const useAccessToken = (): AccessTokenContext => useContext<AccessTokenContext>(AccessToken)
export { AccessTokenProvider, useAccessToken }
You'd have to wrap your app container in AccessTokenProvider:
// index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { AccessTokenProvider } from './providers/AccessTokenProvider'
ReactDOM.render(
<AccessTokenProvider>
<App />
</AccessTokenProvider>,
document.getElementById('app')
)
Then you can then use the hook useAccessToken in App and any children of App. Of course, this provider doesn't have to be root level, but it's easiest to include it here.
// app.tsx
import React, { FC } from 'react'
const App: FC = props => {
const [accessToken, setAccessToken] = useAccessToken()
return <div>{/* content */}</div>
}
export default App
Im working on a fastify powered rest api and im trying to separate my code into logical files. I have some class objects that i import into my server where fastify is defined and the fastify.listen happens. What i cant figure out is how to access the fastify instance inside a file that i import.
app.js
import fastify from 'fastify'
import autoload from 'fastify-autoload'
import { join } from 'desm'
export default function (opts) {
const app = fastify(opts)
app.register(autoload, {
dir: join(import.meta.url, 'routes')
})
return app
}
server.js
import createApp from './app.js'
import 'dotenv/config.js'
import Sessions from './scripts/sessions.js'
import emitter from 'central-event'
async function start () {
const app = createApp({ logger: true })
await app.listen(process.env.PORT || 3000, process.env.IP || '0.0.0.0')
const intervalSeconds = process.env.intervalSeconds * 1000
setInterval(function () {
emitter.emit('heartbeat')
}, intervalSeconds)
}
start()
I want to access the fastify app instance inside sessions.js that is imported into server.js I have tried various things like importing fastify and creating the app in there hoping that it would be inherited etc. Any help would be appreciated.
I found the info i needed. Inside the imports for sessions and others im exporting the class via export default (app) => class Sessions{}
then inside server i import it:
import SessionsImp from './scripts/sessions.js'
then pass the app via:
const SessionsClass = SessionsImp(app)
const Sessions = new SessionsClass()
It seems convoluted but it works as i wish, then i can decorate app with the sessions and other classes im loading and use them inside routes and plugins as i wish.
I am having trouble using an API as it keeps making an https call and not an http call. The https call is behind a paywall and the free version of the api only supports http calls. I am using https://weatherstack.com/ API.
I am using react with the axios package to make my HTTP calls.
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Weather = (props) => {
const [response, setResponse] = useState([])
const hook = () => {
axios
.get(`http://api.weatherstack.com/current?access_key=${process.env.REACT_APP_API_KEY}&query=${props.country.capital}`)
.then(response => {
console.log('promise fulfilled')
setResponse(response.data)
})
}
useEffect(hook, [])
console.log(response)
return (
<div>Temperature: {} </div>)
}
export default Weather
The error message I receive from the API is this
info: "Access Restricted - Your current Subscription Plan does not support HTTPS Encryption."
type: "https_access_restricted"
The strange thing is about 20% of the time the call works and I can get my data, but it doesn't work most of the time. TIA