how can i use async await in regular order? - javascript

when i act onPress onPress={() => Login()} function
first of all, i want to get token by using signInWithKakao function,
second of all, right after i got token, if i have token, i want to dispatch profile by using
kakaoprofile function
if i use my code when i act onPress, this error occure
token is not defined
I think it is because signInWithKakao is not recognized because it is in the Login function.
how can i fix my code?
this is my code
import {
getProfile as getKakaoProfile,
login,
} from '#react-native-seoul/kakao-login';
const Kakao = () => {
const [result, setResult] = useState('');
const Login = () => {
const signInWithKakao = async() => {
const token = await login();
setResult(JSON.stringify(token));
};
if (token) {
const kakaoprofile = async() => {
const profile = await getKakaoProfile();
// console.log("profile:",profile);
dispatch({
type: KAKAOLOG_IN_REQUEST,
data: profile
})
};
}
}
return (
<Container>
<LoginButton onPress = {() => Login()}>
<Label>카카오 로그인</Label>
</LoginButton>
</Container>
);
};
export default Kakao;

You can try to create another function. let's say handleOrder and make it async and then put all your awaits there.
const Login = () => {
handleInOrder()
}
async function handleInOrder() {
try{
const token = await getKakaoProfile()
if(token){
let data = await nextInOrder(token)
//do a dispatch
}
} catch(err){
// handle the error
}
}
Let me know,if you need any help

Related

Updating state with axios response data in reactjs

I am building a website using nextjs and axios. Users can apply to become a member and then be approved by admins. In the admin dashboard I initially load the users and the unapproved users and display them in a list.
When an admin clicks on a button the unapproved user should be approved. The functionality works. The only aspect I can't figure out is how to update the state.
Here is my code:
const AdminIndex = () => {
const [users, setUsers] = useState([])
const [unapprovedUsers, setUnapprovedUsers] = useState([])
useEffect(() => {
loadUnapprovedUsers()
loadUsers()
}, [])
const loadUnapprovedUsers = async () => {
const { data } = await axios.get('/api/admin/unapprovedUsers')
setUnapprovedUsers(data)
}
const loadUsers = async () => {
const { data } = await axios.get('/api/admin/users')
setUsers(data)
}
const approveUnapprovedUser = async (email) => {
try {
const { data } = await axios.put(
`/api/admin/approveUnapprovedUser/${email}`
)
setUnapprovedUsers([]) // only remove the approved user
setUsers(...data) // include the approved user into the array
} catch (err) {
console.log(err)
}
}
}
I am trying to remove the approved user from the unapprovedUsers array and try to add the user to the users array, hence updating the UI. The response returned by axios is an object, which doesn't make things easier.
I would be very thankful for any kind of help!
Just try to filter the unapprovedUsers with the users that don't have that email, also add the approved user to users state
const AdminIndex = () => {
const [users, setUsers] = useState([])
const [unapprovedUsers, setUnapprovedUsers] = useState([])
useEffect(() => {
loadUnapprovedUsers()
loadUsers()
}, [])
const loadUnapprovedUsers = async () => {
const { data } = await axios.get('/api/admin/unapprovedUsers')
setUnapprovedUsers(data)
}
const loadUsers = async () => {
const { data } = await axios.get('/api/admin/users')
setUsers(data)
}
const approveUnapprovedUser = async (email) => {
try {
const { data } = await axios.put(
`/api/admin/approveUnapprovedUser/${email}`
)
setUnapprovedUsers(prev => prev.filter(user => user.email !== email)) // only remove the approved user
setUsers(prev => [...prev, data]) // include the approved user into the array
} catch (err) {
console.log(err)
}
}
}

(React + Firestore) Component executing before Context authentication?

I have a problem with one of my components. The problem I think I have is that my component executes before my user context stores the currentUser. My code only works when doing a hot reload.
The watchlist component gets all the values from the watchlist array where the document matches the currentUser.uid.
UserContext.js:
const [currentUser, setCurrentUser] = useState(null)
const [watchlist, setWatchlist] = useState(null)
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
})
return unsubscribe
}, [])
const getWatchlist = async () => {
const userRef = await getDoc(doc(db, 'users', currentUser.uid))
setWatchlist(userRef.data().watchlist)
console.log(userRef.data().watchlist)
}
These values are the ids of objects I then GET from an API, these are then pushed to the watchlistData array.
CryptoContext.js
export const getWatchlistData = async (list) => {
const watchlistData = []
for (const item of list) {
const result = await axios.get(
`${coingecko}/coins/${item}`
)
watchlistData.push(result.data)
}
return watchlistData
}
And this is how my Watchlist component code currently looks.
WatchlistItems.jsx
const { watchlist, getWatchlist, currentUser } = useContext(UserContext)
const { dispatch } = useContext(CryptoContext)
useEffect(() => {
if (currentUser) {
dispatch({type: 'SET_LOADING'})
const getWatchlistDataFromAPI = async () => {
await getWatchlist()
const watchlistData = await getWatchlistData(watchlist)
dispatch({type: 'GET_WATCHLIST', payload: watchlistData})
console.log(watchlistData)
}
getWatchlistDataFromAPI()
}
}, [currentUser])
If I refresh the page I get "Uncaught (in promise) TypeError: the list is not iterable", but if I do a hot reload, watchlist, and watchlistData both console.log with the correct data.
This is my first post and so please let me know if I've left anything out.
Thank you in advance for any help :)

playwright test website with Keycloak, can't find a way to logIn via pageObjectModel

Hi (i am pretty new in palywright),
I need/want to find a way in playwright, to login via pageObjectModel in a aplication which uses keycloak, but I don't know how.
I found a way without pageObject, to logIn in first test and saving the auth in process.env.STORAGE and then use test.use({storageState: auth_storage_path}) in the rest of the test inside the file.spec.js;
note: keycloak works (sorry for this basic info)
user not login -> visit.baseUrl, redirects you to keycloak authPage
user already logIn -> visit.baseUrl goes direct to bareUrl. (so no logIn button in homepage etc)
//tests_with_auth_store.spec.js
const {test, expect} = require('#playwright/test');
const auth_storage_path = 'storage_auth.json';
const baseUrl = 'https://myBaseUrl_xyz.com';
test('mylogin', async ({page, context}) => {
const usernameId = '[id="username"]';
const passwordId = '[id="password"]';
const idLogin = '[id="login-button"]';
const usernameValue = '*****';
const passwordValue = '*****';
//login:
await page.goto(baseUrl);
await page.fill(usernameId, usernameValue);
await page.fill(passwordId, passwordValue);
await Promise.all([
page.waitForNavigation(/*{ baseUrl: baseUrl }*/),
page.click(idLogin)
]);
process.env.STORAGE = null;
const storage = await context.storageState({ path: auth_storage_path });
process.env.STORAGE = JSON.stringify(storage);
JSON.parse(process.env.STORAGE);
});
test.describe("testDescription login via pageObjectModel", () => {
test.use({storageState: auth_storage_path});
test('i- firstTest whatever ', async ({page}) => {
await page.goto(baseUrl);
......
....
});
test('ii- secondTest whatever ', async ({page}) => {
await page.goto(baseUrl);
......
....
});
});
This works ok and all test under test.use({storageState: auth_storage_path});
can jump to baseUrl directly. The problem is that I can not find a way to encapsulate test('login') into a playwright pageObject (in cypress we did it in simple func in commands.js and saving the auth into cookies)
My demo for login-page.js:
// login-page.js
const { expect, test} = require('#playwright/test');
const baseUrl = 'https://myBaseUrl_xyz.com';
const auth_storage_path = 'storage_auth.json';
exports.LoginPage = class LoginPage {
/**
* #param {import('#playwright/test').Page} page
*/
constructor(page) {
this.page = page;
}
async login() {
process.env.STORAGE = null;
const baseUrl = 'https://myBaseUrl_xyz';
await this.page.goto(baseUrl);
await this.page.fill('[id="username"]', '*****');
await this.page.fill('[id="password"]', '*****');
await Promise.all([
this.page.waitForNavigation(/*{ baseUrl: baseUrl }*/),
this.page.click('[id="fc-login-button"]')
]);
const storage = await this.page.context().storageState({path: auth_storage_path});
process.env.STORAGE = JSON.stringify(storage);
JSON.parse(process.env.STORAGE);
}
// async gotoBaseUrl() {
// test.use({storageState: auth_storage_path});
// return this.page.goto(baseUrl);
// }
}
call login-page from tests_with_auth_store_viaPage.spec.js
// tests_with_auth_store_viaPage.spec.js
const {test, expect} = require('#playwright/test');
const { LoginPage } = require('../login/login-page');
const auth_storage_path = 'storage_auth.json';
const baseUrl = 'https://myBaseUrl_xyz.com';
test('login', async ({page}) => {
const loginPage = new LoginPage(page);
await loginPage.login();
});
test.describe("testDEscription tests with save login into json", () => {
test.use({storageState: auth_storage_path});
test('i- firstTest whatever', async ({page}) => {
await page.goto(baseUrl);
......
....
});
But here test('i- firstTest whatever') page.goto(baseUrl) does NOT jump to baseUrl but to keycloak auth page :(.
Eventhoug test('login') is login and creating storage_auth.json. So I am doing something wrong maybe I need something like loginPage.gotoBaseUrl(), but it doesn't work as well.
By now, I am writing the rest all the test including always the first test('mylogin) but I am sure there is a way via pageObject
Regards
Already found the way. I found myself the way. If someone needs any help, do not hesitate to ask me
demo_login.spec.js
const {test, expect} = require('#playwright/test');
const auth_storage_path = 'storage_auth.json';
const {Login} = require('../../yourpathforfile/login_page.js');
const {Logout} = require("../../yourpathforfile/logout_page.js");
test('login_a', async ({page}) => {
const login = new Login(page);
await login.visit_baseurl();
await login.method_login();
await login.check_login_success();
await login.saveAuth(auth_storage_path);
await login.print_url_tenant();
await login.print_browser();
});
test.describe("Login_a tests --> ", () => {
test.use({storageState: auth_storage_path});
test('demo_a test', async () => {
expect( 1 +1).toBe(2); });
test('logout_a', async ({page}) => {
const logout = new Logout(page);
await logout.visit_baseurl();
await logout.method_check_pageIsWorkplace();
await logout.method_logout_workplace();
await logout.method_check_logout();
});
});
objectPage-> login_page.js
const { expect, firefox} = require('#playwright/test');
const uaParser= require("ua-parser-js");
exports.Login = class Login {
/**
* #param {import('#playwright/test').Page} page
*/
constructor(page) {
this.page = page; }
async visit_baseurl () {
await this.page.goto("/");
//await this.page.goto(process.env.env_baseurl );
}
async method_login() {
const usernameId = selectorUserId;
const passwordId = selectorPassId;
const idLogin = '[id="fc-login-button"]';
const usernameValue = 'demo_user_123';
const passwordValue = 'demo_pass_123';
const mydelay = 200;
await this.page.click(usernameId);
await this.page.type(usernameId, usernameValue, {delay:mydelay});
await this.page.click(passwordId);
await this.page.type(passwordId, passwordValue, {delay:mydelay});
await this.page.click(idLogin,{delay:mydelay})
}
etc ....
}
the same for logout_page
If you need any more info just let mne know.

React settimeout function causing page to refresh repeatedly

My friends and I are trying to create a React App. In this scenario, we want to figure out what user is currently logged in and then send a post request to determine everyone that is in the same "room" as them and display it on the app when the page loads. We send our data back as an array. Though when we console.log our "response" we get multiple outputs. Furthermore, when we try doing setRoomies we get non-stop requests to our server.
Below I have provided our code for React, server, and as well as the console.
function Dashboard() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [user, setUser] = useState('');
const [roomKey, setRoomKey] = useState('')
const [roomies, setRoomies] = useState('')
setTimeout(function () {
const currUser = JSON.parse(localStorage.getItem('user'));
if (currUser) {
setEmail(currUser.email);
setUser(currUser.name);
setRoomKey(currUser.roomKey)
} else {
setUser(null)
}
}, 10);
const payload = {
roomKey: roomKey
}
setTimeout(async function () {
const response = await axios({
url: 'http://localhost:4000/api/dashboard',
method: 'post',
data: payload
})
// setRoomies(response.data.roommates)
console.log(response.data.roommates)
}, 10)
userRouter.post('/dashboard', async function (req, res) {
console.log(req.body)
const sendKey = req.body.roomKey
user.find({ roomKey: sendKey }, await function (err, foundMates) {
console.log(foundMates)
if (err) {
res.send({
token: USER_LOGIN_FAIL
})
} else {
console.log(foundMates);
res.send({
token: USER_LOGIN_SUCCESS,
roommates: foundMates,
})
}
})
})
console
You should not use setTimeout like that. Instead you should use useEffect to achieve what you want. Might require some changes, but the idea is to do something like this
useEffect(() => {
const currUser = JSON.parse(localStorage.getItem('user'));
if (currUser) {
setEmail(currUser.email);
setUser(currUser.name);
setRoomKey(currUser.roomKey)
} else {
setUser(null)
}
}, []);
useEffect(() => {
if(!roomKey) {
return;
}
const payload = {
roomKey: roomKey
}
async function getInfo() {
const response = await axios({
url: 'http://localhost:4000/api/dashboard',
method: 'post',
data: payload
})
// setRoomies(response.data.roommates)
console.log(response.data.roommates)
}
getInfo();
}, [roomKey]);

how can i pass data by using react navigation in react-native?

I have a NotifiCard component and a ReplyComment component
When I run the LookforReply function, the GETONECOMMENT_REQUEST and LOAD_POST_REQUEST dispatches are executed, and the data comes into onecomment.
which is
const {onecomment} = useSelector((state) => state.post);
And I also want to pass the {item:one comment} data in the ReplyComment using navigation.navigate.
However, when we run our code, the data does not come into ReplyComment immediately, so it causing an error.
this is my code
(NotifiCard.js)
const NotifiCard = ({item}) => {
const dispatch = useDispatch();
const navigation = useNavigation();
const {onecomment} = useSelector((state) => state.post);
const LookforReply = useCallback(() => {
dispatch({
type:GETONECOMMENT_REQUEST,
data:item?.CommentId,
}),
dispatch({
type: LOAD_POST_REQUEST,
data:item.PostId,
}),
navigation.navigate('ReplyComment',{itemm:onecomment})
},[]);
return (
<LookContainer onPress={LookforReply}>
<Label>대댓보기</Label>
</LookContainer>
);
};
when dispatch GETONECOMMENT_REQUEST, getonecommentAPI this api run and get data from backend router
(postsaga.js)
function getonecommentAPI(data) {
return axios.get(`/post/${data}/getonecomment`);
}
function* getonecomment(action) {
try {
const result = yield call(getonecommentAPI, action.data);
yield put({
type: GETONECOMMENT_SUCCESS,
data: result.data,
});
} catch (err) {
console.error(err);
yield put({
type: GETONECOMMENT_FAILURE,
error: err.response.data,
});
}
}
which is this backend router
(backend/post.js)
router.get('/:onecommentId/getonecomment', async (req, res, next) => {
try {
// console.log("req.params.onecomment:",req.params.onecommentId);
const onecomment = await Comment.findOne({
where:{id: req.params.onecommentId},
include: [{
model: User,
attributes: ['id', 'nickname'],
}],
})
// console.log("onecomment:",JSON.stringify(onecomment));
res.status(200).json(onecomment);
} catch (error) {
console.error(error);
next(error);
}
});
if i get result data this will put draft.onecomment
(reducer/post.js)
case GETONECOMMENT_REQUEST:
draft.loadPostLoading = true;
draft.loadPostDone = false;
draft.loadPostError = null;
break;
case GETONECOMMENT_SUCCESS:
// console.log("action.data:::",action.data);
draft.loadPostLoading = false;
draft.onecomment = action.data;
draft.loadPostDone = true;
break;
case GETONECOMMENT_FAILURE:
draft.loadPostLoading = false;
draft.loadPostError = action.error;
break;
and i can get data in onecomment by using useselector at (NotifiCard.js)
const {onecomment} = useSelector((state) => state.post);
what i want is that when i press LookforReply i want to pass itemm data to
ReplyComment component but if i press LookforReply, i can't get itemm data
Immediately
(ReplyComment.js)
const ReplyComment = ({route}) => {
const {itemm} = route.params;
console.log("itemm",itemm);
return (
<Container>
<TodoListView parenteitem={itemm} />
<AddTodo item={itemm} />
</Container>
);
};
I think that the LookforReply function is executed asynchronously and navigate is executed before the onecomment data comes in, and it doesn't seem to be able to deliver the itemm.
so how can i fix my code?....

Categories

Resources