I'm trying to call an API by effect call from redux-saga but when will start to call to api throw me an error. Cannot read property 'post' of null
Is really weird because I created a simple function to test my call working example:
function requestGetUser() {
return axios.request({
method: 'get',
url: 'https://my-json-server.typicode.com/atothey/demo/user',
})
}
export function* fetchLoginSaga(action) {
const { data } = yield call(requestGetUser)
yield put(login({ id: data.id, name: data.firstName }))
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
and with this example above works
but when I tried to call a API from class inside of effect call doesn't works
// Depedencies
import axios from 'axios'
export default class BaseService {
/**
* Default http request instane
* @type { Axios.Instance }
*/
instance
/**
* Creates an instance of BaseService.
* @param { String } endpoint To manipulates the operations.
* @param { String } [baseUrl= ] The base url.
*/
constructor(endpoint, baseURL = process.env.BASE_URL) {
this.endpoint = endpoint
this.instance = axios.create({ baseURL })
this.instance.interceptors.response.use(this.responseInterceptor, this.handleResponseError)
}
/**
* Intercepts every response.
* @param { Object } response The response.
* @returns { Promise<Object> }
*/
responseInterceptor = response => response.data
/**
* Intercepts every error on response.
* @param { Object } error The respone error.
* @returns { Promise<Object> }
*/
handleResponseError = error => {
const {
response: {
data: { message },
},
} = error
return Promise.reject(new Error(message))
}
/**
* Make a post request with data.
* @param { Object } [data={}] The data to send as body.
* @param { Object } [requestParams={}] The params to make the request.
* @return { Promise<any> }
*/
post = (data, { url = this.endpoint, ...rest } = {}) => {
const response = this.instance.post(url, data, { ...rest })
return response
}
}
import BaseService from './baseService'
export class AuthService extends BaseService {
/**
* Initializes Auth Service.
*/
constructor() {
super('/auth/local')
}
/**
* Logs Current user.
* @param { String } identifier - User's Identifier
* @param { String } password - User´s password.
* @return { Promise<String> } jwt access token.
*/
async login(identifier, password) {
const user = await this.post({ password, identifier }, { url: '/auth/local' })// when I call return cant find post of null
return user
}
}
export default AuthService
import axios from 'axios'
import { call, takeLatest } from 'redux-saga/effects'
import { fetchLogin } from './authReducer'
import AuthService from 'api/authService'
const authService = new AuthService()
export function* fetchLoginSaga(action) {
const response = yield call(authService.login, 'email', 'password')
console.log({ response })// don't print
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
behind the scenes, redux-saga
will call your function with .apply
, missing the this
context of the authService
object,
detailed information in the repository issue: https://github.com/redux-saga/redux-saga/issues/27
you have 2 ways to fix that:
call
signature to yield call([auth, 'login'], "email", "password");
apply
effect instead - yield apply(auth, auth.login, ["email", "password"]);
or you can bind the parent object to the auth.login
function with plain JavaScript:
yield call(authService.login.bind(authService), 'email', 'password')
I would recommend using the correct effect or effect signature for that instead! 😁
the documentation of "context"/"fn" can be found in redux-saga
docs:
https://redux-saga.js.org/docs/api/#callcontext-fn-args