As title says, I am having issues setting basic auth headers inside a headers object for redux query.
const wooApiHeaders = {
}
const baseUrl = 'https://stagemonkey.dk/kumau';
const createRequest = (url:any) => ({ url, headers: wooApiHeaders })
export const wooApi = createApi({
reducerPath: 'wooApi',
baseQuery: fetchBaseQuery({ baseUrl }),
endpoints: (builder) => ({
getWoo: builder.query({
query: () => createRequest('/wp-json/wc/v3/products')
})
})
})
I have been reading through docs but are facing some issues.
Related
I'm trying to do a delete request. I can fetch the API route through pages/api/people/[something].js.
And this is the response I got from the browser's console.
DELETE - http://localhost:3000/api/people/6348053cad300ba679e8449c -
500 (Internal Server Error)
6348053cad300ba679e8449c is from the GET request at the start of the app.
In the Next.js docs, for example, the API route pages/api/post/[pid].js has the following code:
export default function handler(req, res) {
const { pid } = req.query
res.end(Post: ${pid})
}
Now, a request to /api/post/abc will respond with the text: Post: abc.
But from my API route pages/api/people/[something].js, something is undefined.
const { something } = req.query
UPDATED POST:
React component
export default function DatabaseTableContent(props) {
const id = props.item._id; // FROM A GET REQUEST
const hide = useWindowSize(639);
const [deletePeople] = useDeletePeopleMutation();
async function deleteHandler() {
await deletePeople(id);
}
return <Somecodes />;
}
apiSlice.js
export const apiSlice = createApi({
// reducerPath: "api",
baseQuery: fetchBaseQuery({ baseUrl: url }),
tagTypes: ["People"],
endpoints: (builder) => ({
getPeople: builder.query({
query: (people_id) => `/api/people/${people_id}`,
providesTags: ["People"],
}),
deletePeople: builder.mutation({
query: (studentInfo) => ({
url: `api/people/people-data/student-info/${studentInfo}`,
method: "DELETE",
headers: {
accept: "application/json",
},
}),
invalidatesTags: ["People"],
}),
}),
});
export const {
useGetPeopleQuery,
useDeletePeopleMutation,
} = apiSlice;
pages/api/people/people-data/student-info/[studentInfo].js
import { ObjectId, MongoClient } from "mongodb";
async function handler(res, req) {
const { studentInfo } = req.query; // the code stops here because "studentInfo" is undefined
const client = await MongoClient.connect(process.env.MONGODB_URI.toString());
const db = client.db("people-info");
if (req.method === "DELETE") {
try {
const deleteData = await db
.collection("student_info")
.deleteOne({ _id: ObjectId(studentInfo) });
const result = await res.json(deleteData);
client.close();
} catch (error) {
return res.status(500).json({ message: error });
}
}
}
export default handler;
The order of params passed to your handler functions needs to be reversed.
For NextJS API routes the req is the first param passed to the handler and the res param is second.
Example handler function from NextJS documentation:
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
I'm completely new to using RTK Query, I created the app before but without the authentication and everything worked, now I want to add the authentication using Auth0 but I can't access any file I add getTokenSilently()
PS. getTokenSilently is the {token}
thanks for help
export const myApi = createApi({
reducerPath: "points",
baseQuery: fetchBaseQuery({
baseUrl: "/",
prepareHeaders: (headers, { getState }) => {
const token = getState()
if (token) {
headers.Authorization = `Bearer ${token}`
}
return headers
},
}),
endpoints: builder => ({
getPoints: builder.query({
query: () => `/`,
}),
}),
})
export const { useGetPointsQuery } = myApi
What I ended up doing was to store the token in my state and then added this to App:
useEffect(() => {
(async () => {
try {
const token = await getAccessTokenSilently({})
dispatch(setToken(token))
} catch (e) {
console.error(e);
}
})()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getAccessTokenSilently])
There is a little more logic to know if you have not yet authenticated so that you can render a pending authentication state, but this was enough to get me going.
Hello there I have created dotnet core web api for login and register but in the app after refresh it always tries to log in again. Since I am new to react native I could not apply solutions to my project. I use redux and here is my action :
export const signin = (email, password) => {
return async dispatch => {
const response = await fetch(
'http://localhost:5000/api/user/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
}),
}
);
if (!response.ok) {
throw new Error('Something went wrong!');
}
const resData = await response.json();
console.log(resData);
dispatch({ type: SINGIN, token: resData.token, userId: resData.id });
saveDataToStorage(resData.token);
};
};
const saveDataToStorage = (token, userId) => {
AsyncStorage.setItem('userData', JSON.stringify({
token: token,
})
);
};
And here is my navigator with react navigation 5 :
export const Navigator = () => {
const [userToken, setUserToken] = React.useState(null);
const userData = AsyncStorage.getItem('userData');
const authContext = React.useMemo(() => {
return {
signIn: () => {
setUserToken(userData);
},
singnUp: () => {
setUserToken(userData);
},
signOut: () => {
setUserToken(null);
},
};
}, [userData]);
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer>
<RootStackScreen userToken={userToken} />
</NavigationContainer>
</AuthContext.Provider >
);
};
As I said I could not find a way to apply solutions that I found. Thank you for you help.
First, make sure all of your actions with AsyncStorage should be async(Use promise or async/await).
Then follow this to implement the authentication flow of your application.
https://reactnavigation.org/docs/auth-flow
My this answer will be helpful for you.
React Navigation 5 Auth Flow
So I have recently stared to work with react, I am authenticating a user in my App component like this:
App
signIn(userData) {
console.log(userData)
//do a fetch call to get/users
axios.get('http://localhost:5000/api/users', {
auth: { //set auth headers so that userData will hold the email address and password for the authenticated user
username: userData. emailAddress,
password: userData.password
}
}).then(results => { console.log(results.data)
this.setState({
//set the authenticated user info into state
emailAddress: results.data,
password: results.data.user
});
})
}
and I also have another component called CreateCourse that allows a post request only if I provided the auth header from App,
CreateCourse
handleSubmit = event => {
event.preventDefault();
console.log(this.props)
const newCourse = {
title: this.state.title,
description: this.state.description,
estimatedTime: this.state.estimatedTime,
materialsNeeded: this.state.materialsNeeded
};
axios({
method: 'post',
url: 'http://localhost:5000/api/courses',
auth: {
username: this.props.emailAddress,
password: this.props.password
},
data: newCourse
}).then(
alert('The course has been successfully created!')
).then( () => {
const { history } = this.props;
history.push(`/`)
})
};
I was wondering if I could pass the auth header from App to the children components without using props or context api so that I don't have to manually put the auth headers on every axios request, for reference this is my repo : https://github.com/SpaceXar20/full_stack_app_with_react_and_a_rest_api_p10
I always create a singleton axios instance and set header for it after user signin successful.
let instance = null
class API {
constructor() {
if (!instance) {
instance = this
}
this.request = Axios.create({
baseURL: 'http://localhost:5000',
})
return instance
}
setToken = (accessToken) => {
this.request.defaults.headers.common.authorization = `Bearer ${accessToken}`
}
createCourses = () => this.request.post(...your post request...)
}
export default new API()
After your login successfull, you need call API.setToken(token). Then, when you call Api.createCourse(), the request will have token in headers.
singleton axios instance is the right approach . In the same pattern, use the below method .Import the file wherever required and use axiosapi.get .
const axiosConfig = {auth: {username: XXXX, password: YYYY}};
const axiosservice = axios.create(axiosConfig);
export const axiosapi = {
/**
* Describes the required parameters for the axiosapi.get request
* #param {string} url
* #param {Object} config - The configfor the get request (https://github.com/axios/axios#request-config)
*
* #returns {Promise}
*/
get: (url, config = {}, params) => {
return axiosservice.get(url, {
params,
responseType: 'json',
transformResponse: [
data => {
const parsedData = typeof data === 'string' ? JSON.parse(data) : data;
return get(parsedData);
},
],
...config,
})
.then()
.catch(error => {
return Promise.reject(error);
});
},
}
With vue-resource, we could set the root url in main.js like so:
Vue.http.options.root = 'http://localhost:3000/api'
I tried replacing that with:
axios.defaults.baseURL = 'http://localhost:3000/api';
Vue.prototype.$http = axios
However, now my post calls don't work as expected, and Vue.http.post throws an error.
How is this achieved?
With axios, one can create another instance having a custom config
var my_axios = axios.create({
baseURL: 'http://localhost:3000/api',
});
From here one can use my_axios for operations. You could prototype the custom axios instance into Vue:
Vue.prototype.$http = my_axios
import axios from 'axios';
export const HTTP = axios.create({
baseURL: `http://localhost:3000/api/`,
headers: {
Authorization: 'Bearer {token}'
}
})
You could now use HTTP like so
<script>
import {HTTP} from './http-common';
export default {
data: () => ({
posts: [],
errors: []
}),
created() {
HTTP.get(`posts`)
.then(response => {
this.posts = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>