React sending data from one component to another one - reactjs

This is a function on my Login component page and result.user when user logs in successfully responds with user information. How can I send the result.user information to my main page, so I can set what a user can and can't do?
newLogin = (e) => {
fetch("http://localhost:4000/login", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify(this.state)
})
.then((response) => response.json())
.then((result) => {
console.log(result.user)
});
}

I don't know the structure of your components but You should use react-redux to store your logged-in user because this data is needed to access anywhere in your application and in any component, I highlyl recommend to you to use react-redux for your best practice.
React-redux is easy to use and easy to access any logged-in user's data from the state, so it's better to approach to use react-redux instead of passing data through props.

you can use localStorage to store the data in the browser. in which you can store the data and can use it in anywhere of your code. you don't need to pass the data. when the user log out you need to clear the sorage.
To craete a element in storage
localStorage.setItem('userData', 'result.user')
To clear the data when user logout
localStorage.removeItem('userData');
here userData is representing data stored in the browser.
you can check each time when you needed ,so that whether the user is still logged in using
localStorage.getItem('userData');
if userData is available then you can consider that user is logged in.

Best practice for managing user login in react apps is to use state management for those like Redux and Mobx, you can use React.Context which is easy to use.
In one case I created a wrapper for React.Context.
React-principal
In another case, I created a state management which is so much easier to use react-global-hook

Related

How to properly save sensitive data on frontend using next.js?

I'm building a web app that has role permissions based, admin, user and also products, product A, B, C, etc. I get these data from a backend api.
Currently, I'm using local storage and useContext hook to save and manipulate these data, but an user that knows it, can easily change this information and manipulate the front end, so I'm wondering now which approach I can use here.
My wish (if it's possible) is to get these information by backend after the login, and reuse the data freely in other components, just importing it, like an useContext hook.
I know that there is Redux, but since I'm using next.js, from what I saw, every rendering it will lose/refresh data, so it won't be usefull here.
I'm also using SWR, so, I tried to get these data from cache.get('key'), but the SWR call must be on the same component to get the data properly from the key cached. It's not working if a call the SWR on the e.g home page, and try to get it in other generic component.
What do you people suggest to go here?
Thanks!
I think you should authenticate your user, then store their access key and identifier in localStorage and global state.
When users access an authorization required page.
You'll check for the access token if it doesn't exist on both global state and localStorage. Redirect (or alert) the authorization error.
If there is an access token. Then send a request to the server with that access token. The server will be in charge of authorizing progress. And you will handle the logic on the front end based on the response from the server.
The thing is the authorization (checking permission for instance) should be done in the backend, not on the frontend
I don't know whether you can manipulate the implementation of the backend API or not. Hope it helps
Following the answers, I created a useContext to use in any component that I need.
Here is what I have in my context:
const [userRoles, setUserRoles] = useState<string[] | undefined>([])
const getUsersRoles = useCallback(async () => {
const getUserRoles = await UsersService.getUsersRoles(userInfo.idUsuario)
setUserRoles(getUserRoles.data)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Note: UsersService.getUsersRoles function is integration with the API
And how I use it in the component I need:
const { userRoles, getUsersRoles } = useAuth()
if (userRoles?.length === 0) {
getUsersRoles()
return <LoadingGIf tip="Carregando opções..." />
}
With this, I have the data I need here userRoles. And IF the user reload/refresh the page, getUsersRoles is requested and set the data to the userRoles
The downside to this, at least for me, is that I have to add this:
const { userRoles, getUsersRoles } = useAuth()
if (userRoles?.length === 0) {
getUsersRoles()
return <LoadingGIf tip="Carregando opções..." />
}
for every component I need to use the roles data, but I believe that's it. It's working fine and isn't request extra any endpoints of API.
If anyone has a contribuitions or improves to do in the code, fell free to do it.

How do we persist redux store without using localstorage and make full reactjs web application work offline

I have to do full offline functionality like all redux store data should remain after page refresh/offline(network connection lost).
When user goes offline previously stored data should be used in viewing pages & for suppose i have big forms(ex: employee form with all work experience and personal details)suddenly if user loose network, data should not be lost.. should be saved somehow & after that when user is online have to store data to DB
I am using react -18.0.0 version with react-redux & redux-saga.What are the possible ways?
lets say users are required to log in to system .once login is successfull save that
data to local storage then dispatch loginsuccess with user and token as payloads
execute a function inside useEffect in app.js to get back saved data from local storage and dispatch
loginsuccess with those data
inside signup function:
let res=await axios.post("/signin",{user});
let{user,token}= res.data;
localStorage.setItem("user", JSON.stringify(user));
localStorage.setItem("token",token);
dispatch({ type: "loginsuccess",payload:{user,token}});
inside app.js :
useEffect(() => {
dispatch(isUserLoggedIn());
}, []);
inside isUserLoggedIn :
const localstorage = localStorage.getItem("user");
if (localstorage) {
const user = JSON.parse(localStorage.getItem("user"));
dispatch({ type: "loginsuccess",payload:{user}});
} else {
dispatch({ type: "loginfailed",payload:{error:"please log in"}});
}
One way can be to store your form(or state) in localstorage. Another way can be use library redux-persist .
I think your question is similar to the one asked here. Have a look here for more ideas.
Another approach to store your data, is to make use of the IndexedDB API, it already has a great support on the latest browser versions caniuse.
There is a really good library that make use of this api but
combined with promises idb.
After picking up how you're gonna do it, you can have a watcher saga that reacts to the online / offline status and do the appropriated synchronization.
Also I think it's important to mention that all of the above will only take care of the data, you still need to make sure to make the JS and CSS to be available offline. on web.dev there is a great induction on this subject.

useSWR with data specific to an authenticated user

I want to use SWR to fetch data for the logged in user but I am not sure how to do this in the correct way.
e.g. say i want to get data from the api path api/get/cards for the particular user who is logged in. I could use api/get/cards for they key in SWR but then I assume the cache won't know that the data is specific to the current user only? And then the cache will just provide the data for the last user to user it and not necessarily the user who is currently calling it? What is the best way of doing this?
You can pass an array as the key parameter to useSWR for this precise scenario.
const { data } = useSWR(['/api/get/cards', userId], (url, userId) => { /* Fetching logic */ })
The key of the request will now be the combination of both values, and will revalidate if the userId changes.

How to save data from API to state in Reactjs?

How can I save my object that is fetched from API in state in such a way that after page refresh it should be still available.How to save fetched data from API to state with parameter name?
As i don't want to save object in local storage or session storage.
This can be helpful in such a way that before fetching to the same API it will check if the object is already there then no fetching is required for that API
Suppose mine API look like https://example.com/new/${numberID}/staff
When first time API is executed for the {numberID} => 12ab1 parameter it should store the result for that {numberID} in state now when {numberID}=> 13ab2 parameter is updated again it should store in new state in such a way
Now {numberID} => 12ab1 parameter called again rather fetching from API it should fetch details from state. this will save my API re- hitting
Is this possible using react-hooks?
This is not possible.
State is maintained for the lifetime of the application. When you refresh the page, you are destroying the current instance of the application and creating a new one, therefore state can not be persisted.
The only way to persist data across a refresh is to use third party software or things like browser storage.
Use localStorage API https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
You can put your data in localStorage and get it from there if you need it. For example
if (!localStorage.getItem('data')) {
axios.get(`https://example.com/new/${numberID}/staff`)
dispatch({
type: "FETCHSUCCESS",
payload: response.data
});
localStorage.setItem('data', response.data);
})
.catch(error => {
dispatch({
type: "FETCHFAILURE"
});
});
}

React : How to safely display a component according to user role

I am trying to display an admin Dashboard in react and Meteor only if the current user is an admin.
I am calling a server method that checks the user permission and rendering the admin component only if this method returns true.
This server call is asynchronous and thus the component is not rendering, usually I manage this asynchronous call with state, but I don't want to expose anything in state here (wouldn't like someone to change the state and access the admin dashboard).
Here is the code:
export default class AdminChecker extends Component {
isItAdmin() {
// Get the id of current user
const userId = Meteor.userId();
if (userId) {
// call a server method which returns true if current user is Admin
Meteor.call('checkAdminId', userId, (err, authorized) => {
if (err) {
console.log(err);
return null;
}
return (authorized) ? <AdminDashboard /> : null;
});
}
}
render() {
return (
<div className="admin-temp-container">
{this.isItAdmin()}
</div>
);
}
}
I think I can have this logic in a parent component and send the result of isItAdmin to adminDashboard as a prop (the adminDashboard component would display information only if its props is true).
But I am insure if this is safe. Could one change the props with Chrome react developer tools or something like that?
Thanks a lot
I think there are two parts to this (and the comments are hinting at both):
First, you should not expect to be able to enforce security on the client. You must implement access control logic on the server (i.e., any API that performs an admin action must check that the user performing the action is an admin).
Once you've done that (and perhaps you already have), then you likely need to use props or state to store whether or not the user is an admin (just like you would store any other data in your app).
The key point is that once you enforce security on the server, then it doesn't really matter if a user manipulates the state to get to the admin dashboard: the server will not let the user view any real data or take any actions anyway.
This is completely unrelated to server-side rendering. You can most certainly build a secure admin dashboard without server-side rendering, as long as the APIs used to fetch the admin data and perform admin actions are implementing their own access control checks.

Resources