How to save data from API to state in Reactjs? - 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"
});
});
}

Related

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.

Process fetched data - RTK Query / Redux toolkit / React

I'm new to all mentioned technologies and I'm trying to understand how should I operate in this scenario: I'm trying to fetch a CSV file from an API, once retrieved I want to process it to convert it in a json like object which then I can consume in one of my components.
For instance, I want to view this data in a table and perform operations on this data which causes a change of state for that data.
From the documentation there is a transformResponse field for each endpoint defined which I could use to normalize data needed for my application:
const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({
getPost: build.query<Post, number>({
// note: an optional `queryFn` may be used in place of `query`
query: (id) => ({ url: `post/${id}` }),
// Pick out data and prevent nested properties in a hook or selector
transformResponse: (response: { data: Post }) => response.data,
...
This could work but then I would have some confusion about how I can dispatch actions to change this state.
Another solution would use a Redux Toolkit store slice to save the fetched data and also perform the transform operation and dispatch actions.
Any help would be awesome!
RTK Query state is not meant to be state that is changed locally on the client - RTK Query is a pure cache.
It is meant for a workflow where you
fetch data from the server
display that data
send a request for changes to the server
get new data from the server
display that data again
The purpose of RTK-Query is to make that process as easy as possible for you and take over stuff like automatic re-fetching after something has been triggered to change on the server and removing old values from the cache.
If you want to keep data locally to do local changes on them, you should be using a traditional slice.

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.

React sending data from one component to another one

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

In Redux, is there the concept of Data Provider?

Basically I want to implement an architecture of the type
UserManager.getUser(22)
getUser() -> ReduxStore -> (Does not contain an user with ID 22) -> Goes to User Provider -> User Provider goes to API and returns User object.
Redux Store then saves for subsequent requests and returns User object.
Redux has unidirectional data flow, so the writing and the reading of data are decoupled.
Components read Redux data by subscribing to the store via connect or useSelector, and they write data via disptaching actions in the store.
A selector takes in state and returns a subset of the state, but it does not change the state. A dispatched action can change the state, but it does not return any state.
CQRS (Command Query Responsibility Segregation) is one of the motivations behind Redux. The idea of CQRS is basically to:
use a different model to update information than the model you use to read information
In Redux the update-model is the actions and the read-model is the selectors. To combine them into a single "provider" would be to defeat the purpose of Redux's design.
But if you absolutely had to conflate the two concerns, it might be possible to somehow combine a selector and action-dispatch with a thunk. Again, though, it would not be idiomatic Redux.
Yes we call them action creators. Let's say you're using redux thunk for side effects so getUser will be an action creator that'll first query redux store to see if there is data available if not it'll fetch it from server and store in the redux store like this:
function getUser(id) {
// getState is a function that gives us access to entire redux store
return (dispatch, getState) => {
try {
let user = getState().users.find(x => x.id === id) || null;
if (user) {
dispatch({ type: 'GET_USER', payload: user })
return;
}
user = fetchUserFromServer(id);
dispatch({ type: 'GET_USER', payload: user })
} catch(error) {
// handle error here
}
}
}
Now when next time getUser is called there will be data for that user in the redux store and a call to server will be avoided.
Hope it helps :)

Resources