I'm trying to fetch some data from a endpoint. But when i console.log my response i get undefined. And when I run console.log(g.next().value) I get this in the console {##redux-saga/IO: true, combinator: false, type: "CALL", payload: {…}}. Is the Yield call not executing or?
export function* g2(filterKey: string, filterValue: string) {
try {
const response: Response = yield call(fetchEnglishFilterValue, appSettings.language, filterKey, filterValue);
console.log("response: ", response);
const data: string = yield call([response, response.json]);
console.log("data: ", data);
return data;
} catch (e) {
console.log(e)
}
}
Related
Hi i'm using MeaningCloud's api to get the proper object back once it analyses a string of text or a url for the Natural language processing (NLP). But it doesn't return the proper object.
Right now the code returns a string with the text "[Object object]" on the HTML page. I need it to return the results of the api call which returns the proper JSON object(that I can see in the console) in a proper "key/value" pair format on the HTML page.
Here's my script:
const baseURL = "https://api.meaningcloud.com/sentiment-2.1";
const key = "Your_api_key";
const submitBtn = document.getElementById("submitBtn");
submitBtn.addEventListener("click", (e) => {
e.preventDefault();
const url = document.getElementById("url").value;
if (url !== "") {
getData(baseURL, url, key)
.then(function (data) {
postData("/add", { data: data });
}).then(function () {
receiveData()
}).catch(function (error) {
console.log(error);
alert("Invalid input");
})
}
})
const getData = async (baseURL, url, key) => {
const res = await fetch(`${baseURL}?key=${key}&txt=${url}`)
try {
const data = await res.json();
return data;
}
catch (error) {
console.log("error", error);
}
}
const postData = async (url = "", data = {}) => {
const response = await fetch(url, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
data: data
})
});
try {
const newData = await response.json();
return newData;
} catch (error) {
console.log(error);
}
};
const receiveData = async () => {
const request = await fetch('/all');
try {
// Transform into JSON
const allData = await request.json()
console.log(allData)
// Write updated data to DOM elements
document.getElementById('result').innerHTML = allData;
}
catch (error) {
console.log("error", error);
// appropriately handle the error
}
}
I have another main file that's the server.js file which I run using node server.js that renders the html page properly but the script doesn't render the results on the page properly. You can signup on meaningcloud for a free api key that has a very convenient number of calls you can make.
I need to test redux saga with jest. But it's not working. Here is what I tried
service.js
class Login {
login = async (user: any) => {
try {
const response = await axios({
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
url: `${API.BASE_URL}signIn`,
data: JSON.stringify({
LoginID: user.LoginID,
Password: user.Password,
}),
});
return Bluebird.resolve(response.data);
} catch (err) {
return Bluebird.reject(err);
}
}
}
export default new Login();
worker.js
export function* loginWorker(action) {
try {
const response = yield call(service.login, action.payload);
if (response.Success) {
yield put({type: actionTypes.LOGIN_SUCCESS_ACTION, response});
} else {
toastr.showToast(response.Message);
yield put({type: 'LOGIN_FAILURE', response});
}
} catch (err) {
// dispatch a failure action to the store with the error
yield put({type: 'LOGIN_FAILURE', err});
toastr.showToast(err);
}
}
test.js
describe('test login', () => {
const action = {
type: actionTypes.LOGIN_ACTION,
payload: user,
};
it('login', () => {
const gen = loginWorker(action);
expect(gen.next().value).toEqual(call(service.login, action.payload));
expect(gen.next().value).toEqual(put({type: actionTypes.LOGIN_SUCCESS_ACTION, response}));
});
});
But this function service.login not to be called and I get this error
Cannot read property 'Success' of undefined
Where is my wrong? Please help
I would like to make a request about the api rick and morty. To get the details of a character, you have to specify an id as a parameter:"https://rickandmortyapi.com/api/character/id"
I use redux-saga to fetch my request, but the request fails with a message:
" Hey! that parameter is not allowed, try with a number instead;)"
I tried the request with the id received in my component and the request is effective. I think it comes either from my action or my saga.......
here is my action :
export const getCharactersDetails = () => {
return { type: GET_CHARACTER_DETAILS }
}
here is my saga :
const getLatestDetails = (id) =>
fetch('https://rickandmortyapi.com/api/character/' + id);
export function* fetchCharacterDetails() {
try {
let myCharacter;
const response = yield call(getLatestDetails);
const result = yield response.json();
if (result.error) {
yield put({ type: DETAILS_REQUEST_FAILED, error: result.error });
} else {
myCharacters = result.results
yield put({ type: DETAILS_RECEIVED, character: myCharacter });
}
} catch (error) {
yield put({ type: DETAILS_REQUEST_FAILED, error: error.message });
}
}
function* actionWatcher() {
yield takeLatest(GET_CHARACTERS, fetchCharacters)
yield takeLatest(GET_CHARACTER_DETAILS, fetchCharacterDetails)
}
and i call my action like that:
let CharacterId = this.props.navigation.state.params.id
this.props.dispatch(getCharactersDetails(CharacterId))
any idea what I'm not doing right?
You are not passing any ID to your getLatestDetails function.
Add the ID to the action you are creating:
export const getCharactersDetails = id => {
return { type: GET_CHARACTER_DETAILS, id }
}
…then add the ID from the action as parameter to your saga and pass it as second argument to your call effect:
export function* fetchCharacterDetails({ id }) {
try {
let myCharacter;
const response = yield call(getLatestDetails, id);
const result = response.json();
if (result.error) {
yield put({ type: DETAILS_REQUEST_FAILED, error: result.error });
} else {
myCharacters = result.results
yield put({ type: DETAILS_RECEIVED, character: myCharacter });
}
} catch (error) {
yield put({ type: DETAILS_REQUEST_FAILED, error: error.message });
}
}
Additional explanation:
The saga gets the action as argument; we are using destructuring here to get just the ID (note the curly braces)
call accepts the function to be called as first parameter, followed by additional arguments passed to the function, this is how getLatestDetails gets the ID
I removed yield before response.json(), this is just a plain old synchronous operation
I tried to make an API call, but the yield put fired before the yield call finished the execution. Here is my code:
Api.js
function callApi(endpoint, token = null) {
const fullUrl =
endpoint.indexOf(API_ROOT) === -1 ? API_ROOT + endpoint : endpoint;
return axios
.get(fullUrl, { headers: { Authorization: token } })
.then(resp => {
return Object.assign([], resp.data);
})
.catch(error => ({ error: error.message || "Something bad happened" }));
}
export const checkOpenRegister = (branchId, userId, token) => {
console.log("in check open");
callApi(
`Branches/${branchId}/registers?filter[where][status]=1&filter[where][userId]=${userId}`,
token
);
};
and in my saga index.js
function* doCheckAuthInfo() {
try {
const user = yield select(getUser);
if (user.token) {
yield put({
type: CHECK_AUTH_INFO_SUCCEED,
payload: { token: user.token }
});
yield put({ type: CHECK_OPEN_REGISTER_REQUESTED });
} else {
//redirect to login
yield put(NavigationActions.navigate({ routeName: "Login" }));
}
} catch (error) {
yield put({ type: CHECK_AUTH_INFO_FAILED, error });
}
}
function* doCheckOpenRegister() {
try {
const user = yield select(getUser);
const response = yield call(
checkOpenRegister,
user.branchId,
user.userId,
user.token
);
yield put({ type: CHECK_OPEN_REGISTER_SUCCEED, payload: response });
} catch (error) {
yield put({ type: CHECK_OPEN_REGISTER_FAILED, error: error.message });
}
}
function* watchCheckAuthInfo() {
yield takeLatest(CHECK_AUTH_INFO_REQUESTED, doCheckAuthInfo);
}
function* watchCheckOpenRegister() {
yield takeLatest(CHECK_OPEN_REGISTER_REQUESTED, doCheckOpenRegister);
}
// use them in parallel
export default function* rootSaga() {
yield all([
fork(watchCheckAuthInfo),
fork(watchCheckOpenRegister)
]);
}
In my saga, on function doCheckOpenRegister, yield PUT fired with no payload but I can find the payload in my network debugger.
I need the payload to trigger action to redirect. In this case, when there is a value in response I need to redirect to main page.
you forgot return Promise from function checkOpenRegister
export const checkOpenRegister = (branchId, userId, token) => {
console.log("in check open");
return callApi(
`Branches/${branchId}/registers?filter[where][status]=1&filter[where][userId]=${userId}`,
token
);
};
I have a redux-saga as below:
export function* loadApplianceSaga() {
try {
let {request, success, error} = yield take(ActionTypes.APPLIANCE.LOAD);
request.url = yield select(getResourceLink, request.resource);
const response = yield call(makeRequest, request);
if (!response.error) {
yield put({type: success, payload: response.body});
} else {
yield put({type: error, payload: response});
}
} catch (e) {
yield put({type: ActionTypes.REQUEST.CALL_ERROR, error: e});
}
}
export function* watchLoadAppliance() {
while (true) {
yield* takeEvery(ActionTypes.APPLIANCE.LOAD, loadApplianceSaga);
}
}
and root saga:
export default function* rootSaga() {
yield [
fork(watchLoadAppliance)
]
}
I'm facing a problem that loadApplianceSaga doesn't work at the first time. I logged and saw that in the first time it only dispatched ActionTypes.APPLIANCE.LOAD action then no action is dispatched. But in the second time, I can see success action or failed action which are dispatched.
Could anyone tell me what was wrong? Thanks in advance!
Updated action:
export const loadAppliances = () => {
return {
type: ActionTypes.APPLIANCE.LOAD,
request: {
resource: Resources.Appliances,
param: {
page: 0,
size: 5,
sort: 'name,desc'
},
header: {
Accept: 'application/json'
}
},
success: ActionTypes.APPLIANCE.LOAD_SUCCESS,
error: ActionTypes.APPLIANCE.LOAD_ERROR
}
};
you have used take two times.
try
export function* loadApplianceSaga(action) {
try {
let {request, success, error} = action;
request.url = yield select(getResourceLink, request.resource);
const response = yield call(makeRequest, request);
if (!response.error) {
yield put({type: success, payload: response.body});
} else {
yield put({type: error, payload: response});
}
} catch (e) {
yield put({type: ActionTypes.REQUEST.CALL_ERROR, error: e});
}
}
export function* watchLoadAppliance() {
while (true) {
yield* takeEvery(ActionTypes.APPLIANCE.LOAD, loadApplianceSaga);
}
}