delay rendering untilthe fetching is complete - reactjs

I am using react Context and useReducer to fetch the data. I am working with front end right now. i have some problems.
this is State
const initialState = {
users: [
{
name: "Kyaw Zin Thih",
type: "Private University",
subjects: ["IT", "Business"],
phNumbers: ["111-111-111", "222-222-222"],
about: "llorem",
location: "loremlorem",
},
],
currentProfile: {},
currentPosts: [],
};
Inside users there will be a lot of users data from database. inside the currentProfile there will only be the data of that the user is viewing. same for currentPosts. when the user leave profile page both of the state will be empty again
My UI is like that. In main page there will be containers that show some data from "users". if someone click the container router will lead to Profile page. when someone reach the ProfilePage i will use useEffect to load the data to the "currentProfile" part
useEffect(() => {
setcurrent(username);
return () => {
deletecurrent();
};}, []);
const publicdata = useContext(PulicDataContext):
let { url } = useRouteMatch();
const { username } = useParams();
const {
setcurrent,
currentProfile,
currentPost,
deletecurrent,
loading,} = publicdata;
const { name, type, subjects, phNumbers, location, about } = currentProfile;
The Problem is that when the profile page is loaded current profile is emply until it is loaded in useEffect. So names, types and so on, they are also emply when the component load. Therefore react will only show blanks in "return" part.
how can i fix that thing.

Related

Laravel Inertia React preserve state not working

I'm trying to reload my page but keep the filters state with Inertia.
Like this:
const [allProducts, setAllProducts] = useState([]);
const [filters, setFilters] = useState([]);
const fetchProducts = (page) => {
Inertia.get(
`/products?page=${page}`,
{ filters },
{
preserveState: true,
preserveScroll: true,
only: ['products'],
onSuccess: (response) => {
setAllProducts(allProducts.concat(response.props.products.data));
page += 1;
}
}
)
});
The problem is that filters and allProducts are reset even though preserveState = true.
What do you mean by "reload my page"? State in React is not preserved on "real" page refresh.
Maybe you can save data in local storage, then load it by useEffect. Another solution is to store data you want to keep between pages in Laravel session storage.

React Recoil: State not being saved across navigation to different URLs within App

I'm getting started with Recoil for a React App, but running into some issues, or at least some behavior I'm not expecting.
I'd like to be able to use one component to render many different "views" based on the URL. I have a useEffect in this component that switches based on the location.pathname and based on that pathname, it'll make an API call. But before it makes the API call, it checks the length of the atom to see if it's empty or not, then will call the API and set the atom based on the API call.
However, when I navigate to a different URL and come back to one I've already visited, the API is called again, even though I've previously set the state for that URL.
The behavior I'm expecting is that once a URL has been visited and the return from the API is stored in an Atom, the API call isn't made again when leaving the URL and coming back.
Relevant code below:
Atom.js
export const reports = atom({ key: "reports", default: { country: [], network: [], }, });
the one component that will render different data based on the reports atom.
import { useRecoilState } from "recoil";
import { reports } from "../globalState/atom";
const TableView = ({ columns, }) => {
const location = useLocation();
const [report, setReport] = useRecoilState(reports);
const currentView = location.pathname.split("/")[1];
useEffect(() => {
const getReportsData = async () => {
switch (location.pathname) {
case "/network":
if (report[currentView].length === 0) {
const response = await fetch("/api");
const body = await response.json();
setReport(
Object.assign({}, report, {
[currentView]: body,
})
);
console.log('ran')
break;
}
getReportsData();
}, [])
As previously mentioned, that console.log is ran every time I navigate to /network, even if I've already visited that URL.
I've also tried doing this with selectors.
Atom.js
export const networkState = atom({
key: "networkState",
default: networkSelector,
});
export const networkSelector = selector({
key: "networkSelector",
get: async ({ get }) => {
try {
const body = await fetch("/api/network").then((r) => r.json());
return body;
} catch (error) {
console.log(error);
return [];
}
}
Component
import {useRecoilStateLoadable} from "recoil"
import {networkState} from "../globalState/atom";
const Table = ({columns}) => {
const [networkData, setNetworkData] =
useRecoilStateLoadable(networkState);
And then a switch statement based on networkData.state
}
Any help would be greatly appreciated, thank you!

React Context data is empty after routed to next Page

I have a small dummy react application, I have created a "Home Page" after the user is logged on the home page context is set for user credentials from the home page and I am able to get it on the home page. but I have created another page "profile" after I change the route to profile in URL, there is no longer data. I understand that since the page is refreshed data is lost because data persistence is the job of databases. but if I have to query some common data for every page what advantage does context put on the table? thanks.
On Home Page below the code, I wrote to set user credentials.
Home.js
**const { userCredentails, setUserCredentails } = useUserContext();**
useEffect(() => {
const getInitialData = async () => {
const returnData = await AuthFunction();
if (returnData.success) {
**setUserCredentails(returnData.user);**
return dispatch({ type: true, userData: returnData.user });
}
return dispatch({ type: false });
};
getInitialData();
}, []);
Now if a want to access the same data on the profile I don't want to query the database how do get it from there.
**const cntx = useContext(userCredentialsContext);**
above code returns empty objects.
finally, this is the context.js page
import { useState, createContext, useContext } from "react";
export const userCredentialsContext = createContext({});
export const UserContextProvider = ({ children }) => {
const [userCredentails, setUserCredentails] = useState({});
return (
<userCredentialsContext.Provider
value={{ userCredentails, setUserCredentails }}
>
{children}
</userCredentialsContext.Provider>
);
};
export const useUserContext = () => {
const data = useContext(userCredentialsContext);
return data;
};
if you implement your routing by using an anchor tag() or window.location, then the whole page will refresh including your context, setting it back to default state, the right way to do it is by using the Link tag from react-router-dom, here is an example;
import { Link } from "react-router-dom";
<Link to="/home">Home</Link>

How to to be displayed reactour just first time in nextjs?

I'm using reactour in next.js
I want to just first time when page is rendered reactor to be displayed, and when route change and come back to this page reactor not to be displayed
how can do this?
this is how I call it
import { disableBodyScroll, enableBodyScroll } from "body-scroll-lock";
import dynamic from "next/dynamic";
const Tour = dynamic(() => import("reactour"), { ssr: false });
const tourConfig = [
{
selector: ".step_1",
content:
'Click "View future forecast earning" to look at all....',
},
{
selector: ".step_2",
content:
"Chose different earning forecasts to see how your property...",
},
];
export default function MyPage(props) {
const disableBody = target => disableBodyScroll(target);
const enableBody = target => enableBodyScroll(target);
const [isTourOpen, setIsTourOpen] = useState(false);
const closeTour = () => setIsTourOpen(false);
useEffect(() => {
const timing = setTimeout(() => {
setIsTourOpen(true);
}, 2000);
return () => {
clearTimeout(timing);
};
}, []);
return (
<>
<OtherComponent />
<Tour
onRequestClose={closeTour}
steps={tourConfig}
isOpen={isTourOpen}
rounded={5}
onAfterOpen={disableBody}
onBeforeClose={enableBody}
className={classes.root}
disableInteraction
inViewThreshold={50}
/>
</>
);
}
This entirely depends on your logic you can do this in 3 ways if you like:
The local storage way:
localStorage.setItem('displayTour', true);
If you're not clearing out the local storage then you can always check your storage whenever the user signs in to check (in useEffect) if the tour is displayed to them or not.
Storing in cookies:
You can always set cookies for the first time the user signs in and check, but this approach has a con, cookies are set in the browser so if the user has already gone through the tour and they sign in from another browser the tour will be rendered again.
Tour Flag from API (Network Request):
This may be the right thing to do if you are not trying to save your network requests. You can always send back a flag from backend e.g is_tour_displyed: false and can always validate whether to show the tour or not.
Note: The localStorage and the cookies may be cleared out anytime, considering if that's not a problem for you. You can always go for the third option.
you can make condition and add a value to localStorage like blow:
localStorage.setItem('playTour', 'true');
and when ever you played the tour at first time you can set this value to false

Strategy to overcome caching of Axios requests?

I've noticed that if I make a GET call to the same API endpoint twice in a row then the previous result appears to get cached. This is causing a problem for the logic of my React component which is a multi-page Wizard.
I define my API request like this:
const [{ data, isLoading, isError }, userNameDoFetch] = useFetch(
null,
{ }
)
The user can then enter a username into an input element and its existence is checked liked this:
const handleBlur = (event) => {
const propName = event.target.name;
const propValue = event.target.value;
if (propValue.length > 0) {
setIsFetching(true);
userNameDoFetch( `${API_ROOT()}account_management/users/name/${propValue}` );
}
}
}
I then have a useEffect that processes the data coming back from the server. It begins like this:
useEffect(() => {
setIsFetching(false);
...
The problem is that the useEffect isn't called if say, the user tabs back into the Username field and then tabs out again. This sets isFetching to true, which disables the Next button in my wizard, leaving the user trapped on that page.
Any thoughts on how to resolve this?

Resources