How to run useEffect in React after POST request? - javascript

Tasks doesn't update (not unless I refresh the page) after submitting/creating a new task. Seems like the useEffect is not running during handleSubmitForm.
import React, { useEffect, useState } from "react";
const Tasks = () => {
const [tasks, setTasks] = useState([]);
useEffect(() => {
getTasks();
}, []);
const getTasks = async () => {
const response = await ('/tasks/');
const data = await response.json()
setTasks(data);
};
const [task, setTask] = useState("");
const handleSubmitForm = (e) => {
fetch("/tasks/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: task, completed: false }),
})
};
return (
<ul>
<div>
<input
onInput={(e) => {
setTask(e.target.value);
}}
value={task}
/>
<button onClick={handleSubmitForm}>Add</button>
</div>
{tasks.map((task) => {
return <li key={task.id}>{task.title}</li>;
})}
</ul>
);
};
export default Tasks;
I'm fairly new with react and it's 2 days now I still can't figure it out.

After successfully submitting a new task, you should add it to your tasks array. After that React will automatically re-render your tasks for you (since your tasks state was updated).
const handleSubmitForm = (e) => {
fetch("/tasks/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: task, completed: false }),
}).then(() => {
setTasks([...tasks, { title: task, completed: false }]);
})
};

All you have to do is call getTasks() in the .then of your fetch function
const handleSubmitForm = (e) => {
fetch("/tasks/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: task, completed: false }),
}).then(() => {
getTasks();
})
};

Related

Having Error: Exception in HostFunction: Malformed calls from JS: field sizes are different

I'm having Error Exception in HostFunction: Malformed calls from JS: field sizes are different while connecting API. Below I have attached the error screenshot and the code. Please do help me out.
Error Screenshot:
const { myToken } = useContext(AuthContext);
const [pendingApiData, setPendingApiData] = React.useState([]);
const [isFetching, setIsFetching] = useState(false);
const FetchList = () => {
const abortCont = new AbortController();
axios({
method: 'get',
url: URLs._pendingReceipt,
headers: {
Accept: "application/json",
Authorization: myToken,
'Content-Type': 'application/json',
},
signal: abortCont.signal,
}).then(function (result) {
setPendingApiData(result.data.pendingData);
}).catch(function (error) {
Alert.alert("Error", error);
});
setIsFetching(false);
return () => abortCont.abort();
}
useEffect (() => {
FetchList();
}, []);
const onRefresh = () => {
setIsFetching(true);
FetchList();
};

Vue send request when declared params changed from empty string

In my app I'm sending a request to my backend app from which I get a response with id like { 'id': '12345'}. I saves this id as loadId inside data, here:
export default {
name: 'SyncProducts',
data() {
return {
loadId: '',
Now I want to send another POST fetchSyncedProductsResultRequest when this data loadId change from empty. How to do so?
Below my code:
imports.js
const createApparelMagicProductsRequest = (self, products) => {
const jwtToken = self.$store.state.idToken;
console.log(products)
console.log()
const payload = JSON.stringify({ product_codes: products['product_codes'].split(',') })
return axios
.post(`/api/v1/imports/products_batches`, payload,{
headers: {
Authorization: `Bearer ${jwtToken}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(response => response.data['id'])
};
const fetchSyncedProductsResultRequest = (token, id) => {
return axios
.get(`/api/v1/imports/products_batches`, {
params: { id: id },
headers: {
Authorization: `Bearer ${token}`,
}
})
.then(response => {
return response.data['result']
})
};
sync_products.vue
<script>
import {
fetchSyncedProductsResultRequest,
createApparelMagicProductsRequest
} from '../../api/imports'
export default {
name: 'SyncProducts',
data() {
return {
styleCodes: [],
fetchedProductSyncResult: [],
loadId: '',
}
},
async mounted() {
await fetchSyncedProductsResultRequest(this, load.id)
this.syncedProductsFetched = true
this.pageChanged(this.currentPage)
},
async mounted() {
const jwtToken = this.$store.state.idToken;
fetchSyncedProductsResultRequest(jwtToken).then(data => {
this.fetchedProductSyncResult = data
})
},
</script>
Use a watcher on loadId that calls fetchSyncedProductsResultRequest() with the new value if it's changed from an empty string to a non-empty string:
export default {
watch: {
loadId(newValue, oldValue) {
if (!oldValue && newValue) {
const jwtToken = this.$store.state.idToken;
fetchSyncedProductsResultRequest(jwtToken, newValue).then(data => {
this.fetchedProductSyncResult = data
});
}
}
}
}
demo

How to map this given api response in react js javascript

I am getting an error when i was calling an post request in use effect hook and i got the response as promise pending, but the object is there, please see the response and please provide a perfect code to map this response.
code
function Comment({ id }) {
const [data, setdata] = useState([]);
console.log(id);
useEffect(() => {
const query = `
query{
forumAnswerId(id:${id}){
forumAnswerBody
forumAnswerTime
forumAnswerCode1
forumAnswerCode2
forumAnswerCode3
forumAnswerAuthor
forumAnswerBoolean
forumAnswerCode1Title
forumAnswerCode2Title
forumAnswerCode3Title
}
forumComment(forumAnswerComment:${id}){
forumAnswerCommentPost
forumAnswerCommentBody
forumAnswerCommentAuthor
forumAnswerCommentTime
}
}
`;
const opts = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
};
const res = fetch('http://127.0.0.1:8000', opts).then((res) => res.json());
setdata(res);
}, []);
return <div></div>;
}
export default Comment;
here you are:
fetch('http://127.0.0.1:8000', opts)
.then((res) => res.json())
.then(r=> setdata(r))
promise result cannot be accessed outside. You need to set data inside the then function
Using Promise
fetch('http://127.0.0.1:8000', opts).then((res) => setdata(res.json()));
Using Async await
const res=await fetch('http://127.0.0.1:8000', opts)
setdata(res.json())
useEffect(() => {
const fetchData = async () => {
const query = `
query{
forumAnswerId(id:${id}){
forumAnswerBody
forumAnswerTime
forumAnswerCode1
forumAnswerCode2
forumAnswerCode3
forumAnswerAuthor
forumAnswerBoolean
forumAnswerCode1Title
forumAnswerCode2Title
forumAnswerCode3Title
}
forumComment(forumAnswerComment:${id}){
forumAnswerCommentPost
forumAnswerCommentBody
forumAnswerCommentAuthor
forumAnswerCommentTime
}
};`
const opts = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
};
const res = await fetch('http://127.0.0.1:8000', opts).then((res) => res.json());
setdata(res);
}
fetchData();
}, []);

401 Unauthorized, SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

Hi all I'm new to authentication. I was building an app where a user can login and create a story using an api, and the story is sent to the backend using a POST request. The app was authenticating fine, until I built the app. Now when I sign in and try to add a story, I get 401 Unauthorized and SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data in actions.js.
Then if I refresh the page, the errors go away and the app is working.
I am able to logout and login again normally.
I have no idea why that's happening. Any help will be appreciated.
The backend server does say Error in authorization JsonWebTokenError: jwt malformed
actions.js
import * as t from './actionTypes';
import { setUserSession } from '../utils/Common';
import { getToken } from '../utils/Common'
const token = getToken();
// this is what our action should look like which dispatches the "payload" to reducer
const setLoginState = (loginData) => {
return {
type: t.SET_LOGIN_STATE,
payload: loginData, //{ ...json, userId: email }
};
};
const setStoryState = (storyData) => {
return {
type: t.CREATE_STORY,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
const getStoryState = (storyData) => {
return {
type: t.GET_STORIES,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
const getSingleStoryState = (storyData) => {
return {
type: t.GET_STORY,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
export const login = (loginInput) => { //our login action
const { email, password, isAdmin } = loginInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(loginInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
// console.log(json)
dispatch(setLoginState({ ...json, userId: email, isAdmin: isAdmin })); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
setUserSession(json.token, json.lastName)
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
};
export const getStories = () => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(getStoryState( [...json ])); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
export const viewStory = id => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch(`http://localhost:3000/api/v1/stories/${id}`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(getSingleStoryState( {...json } )); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
export const roleChange = () => {
return {
type: t.SET_ROLE_STATE,
//payload: role
};
}
export const logout = () => {
return {
type: t.LOGOUT,
};
}
export const createStory = storyInput => {
console.log(token)
const { summary, description, type, complexity, time, cost } = storyInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(storyInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
//dispatch(setStoryState( [...json ]));
dispatch(setStoryState({ // our action is called here with object as parameter, this is our payload
summary: summary,
description: description,
type: type,
complexity: complexity,
time: time,
cost: cost
})); // our action is called here
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Some error occured, please retry');
console.log(err);
});
};
}
export const addStory = story => {
return {
type: t.ADD_STORY,
payload: story,
}
}
export const setStatus = (id, status) => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch(`http://localhost:3000/api/v1/stories/${id}/${status}`, {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'text/html',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
// dispatch(getStoryState( {...json } )); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
CreateStory.js
import React, { useState } from 'react'
import { createStory } from '../redux/actions'
import { useDispatch, useSelector } from "react-redux";
import history from '../utils/history';
import { withRouter } from 'react-router-dom';
const CreateStory = () => {
const [summary, setSummary] = useState("");
const [description, setDescription] = useState("");
const [type, setType] = useState("");
const [complexity, setcomplexity] = useState("");
const [time, setTime] = useState("");
const [cost, setCost] = useState(0);
const usedispatch = useDispatch();
const userCreateStory = (summary, description, type, complexity) => usedispatch(createStory({
'summary': summary,
'description': description,
'type': type,
'complexity': complexity,
'time': time,
'cost': cost
}));
const handleSummaryChange = e => {
setSummary(e.target.value)
}
const handleDescriptionChange = e => {
setDescription(e.target.value)
}
const handleTypeChange = e => {
setType(e.target.value)
}
const handleComplexityChange = e => {
setcomplexity(e.target.value)
}
const handleTimeChange = e => {
setTime(e.target.value)
}
const handleCostChange = e => {
setCost(e.target.value)
}
// const currStory = useSelector((state)=> state.storyReducer.story)
const handleSubmit = e => {
e.preventDefault();
userCreateStory(summary,description,type,complexity,time,cost)
setTimeout(()=> history.push("/userStories"), 1000 );
//setTimeout(()=> console.log(currStory) ,1000)
}
return (
<div>
<form className='create-story-form'>
<label for="summary">Summary:</label>
<input name="summary" type='text' onChange={handleSummaryChange}/>
<label for="desc">Description:</label>
<textarea name="desc" type='text' onChange={handleDescriptionChange}/>
<label for="type">Type:</label>
<select name="type" onChange={handleTypeChange}>
<option value="enhancement" defaultValue>Enchancement</option>
<option value="bugfix">Bugfix</option>
<option value="development">Development</option>
<option value="qa">QA</option>
</select>
<label for="complexity">Complexity:</label>
<select name="complexity" onChange={handleComplexityChange}>
<option value="low" defaultValue>Low</option>
<option value="mid">Mid</option>
<option value="high">High</option>
</select>
<label for="time">Estimated time for completion:</label>
<input name="time" type='text' onChange={handleTimeChange}/>
<label for="cost">Cost:</label>
<input name="cost" type='number' onChange={handleCostChange}/>
<button onClick={handleSubmit}>Submit</button>
</form>
</div>
)
}
export default withRouter(CreateStory);
Login.js
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { login, roleChange } from '../redux/actions' //OUR ACTIONS
import { useSelector } from 'react-redux'
import history from '../utils/history';
import { withRouter } from 'react-router-dom';
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isAdmin, setIsAdmin] = useState(false);
const usedispatch = useDispatch();
const userLogin = (email, password, isAdmin) => usedispatch(login({'email': email, 'password': password, 'isAdmin': isAdmin }));
const handleRoleChange = e => {
setIsAdmin(true)
if(isAdmin)
setIsAdmin(false)
console.log(isAdmin)
}
const handleEmailChange = e => {
setEmail(e.target.value)
}
const handlePasswordChange = e => {
setPassword(e.target.value)
}
const handleSubmit = e => {
e.preventDefault();
userLogin(email, password, isAdmin)
setTimeout(()=> history.push("/user"), 1000 );
}
const disabled = () => {
return email === "" || password === ""
}
return (
<div>
<form className='login-form'>
<input type='email' name='email' placeholder='Email' onChange={handleEmailChange}/>
<input type='password' name='password' placeholder='Password' onChange={handlePasswordChange}/>
<button type='submit' disabled={disabled()} onClick={handleSubmit}>Login</button>
</form>
<button onClick={handleRoleChange}>Switch to {isAdmin ? 'user' : 'admin'}</button>
</div>
)
}
export default withRouter(Login);
reducers.js
import { initialState } from './initialState';
import * as t from './actionTypes';
export const loginReducer = (state = initialState, action) => {
switch (action.type) {
case t.SET_ROLE_STATE:
return {
...state,
isAdmin: true
};
case t.SET_LOGIN_STATE:
return {
...state,
...action.payload, // this is what we expect to get back from API call and login page input
isLoggedIn: true, // we set this as true on login
};
case t.LOGOUT:
return {
initialState
};
default:
return state;
}
};
export const storyReducer = (state = [], action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
stories: [...state.stories, action.payload],
};
case t.GET_STORIES:
return {
...state,
stories: action.payload,
};
case t.GET_STORY:
return {
...state,
story: action.payload,
};
// case t.ADD_STORY:
// return {
// ...state,
// stories: [...state.stories, action.payload], //stories is an object
// };
case t.LOGOUT:
return {
stories: [{complexity: "",
cost: 0,
description: "",
summary: "",
time: "",
type: ""}]
};
default:
return state;
}
}

How to persist Login with token?

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

Categories

Resources