Rest API calls in REACT - reactjs

I am working on existing code base for a react application. I am new to React and the developer who wrote this left.
In my current code base "request-promise-native" is pass from one component to another component using props. I don't get this. Why not just import it again in every component?
App.tsx
import rp from 'request-promise-native';
const App: React.FC = () => {
return (
<Router>
<Route path="/" render={(props) => <Main {...props} rp={rp} />}></Route>
</Router>
)
};

After reading the documentation of https://www.npmjs.com/package/request-promise it appears this is completely pointless and you are correct about imports.

Related

React router/lazy suspense + useTransition - How to stay on current page until next page is rendered?

At this point if someone can figure this out I would be willing to pay some money.
My question pertains to using React Router and the new React 18's useTransitions. At the current stage, lazy loading is implemented using React.lazy and React.Suspense around the routes with the fallback being some React component you choose. As people have noticed, there is 'flickering' etc. So now there is useTransitions. Does anyone have an implementation using these to make it so you can stay on the current rendered page until the next page is ready to load.
I have seen this post: React lazy/Suspens + React Router dont change route until component is fetched
But it does not seem to work. I'm using react-router v5 and react v18.2. I have seen many people ask something similar, but if someone could share their implementation, I believe it would benefit more than myself.
I appreciate your time to view this. Thank you.
You can try with route-level-code-split for that you need to create custom FallbackProvider and utils. Which helps you store your current component until the next page is not loaded yet.
Here is the example Demo
Source code Link
This worked for me: React lazy/Suspens + React Router dont change route until component is fetched
Note the updated React 18 version of SuspenseRouter.
My suggestion for React v18 + React-Router-Dom v6 + Webpack would be to use #loadable/component
https://www.npmjs.com/package/#loadable/component
https://github.com/gregberge/loadable-components
Replace this:
import React, {lazy, Suspense} from 'react'
import { Routes , Route} from "react-router-dom"
const Home = lazy(() => import(/* webpackChunkName: "routes-home" */ './routes/Home'))
export default function App(){
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/routes/home" element={<Home />} />
</Routes>
<Suspense />
)
}
With this:
import loadable from '#loadable/component'
const Home = loadable(() => import(/* webpackChunkName: "routes-home" */ './routes/home'))
export default function App(){
return (
<Routes>
<Route path="/routes/home" element={<Home />} />
</Routes>
)
}
P.S. /* webpackChunkName: "routes-home" */ is optional

Combining useContext Providers

as im creating a reactjs project , i have devided my context into three separate files , therefore i ended up with three context providers , at first i wrapped all the context providers one by one around my components in app.js , but i figures maybe if i combined all the context providers in one component and use this component to wrap my app.js so i created the file with below code
import React from "react";
import CryptoContextProvider from "./crypto-context";
import NewsContextProvider from "./news-context";
import DataContextProvider from "./index-context";
const allContextProviders = (props) => {
return (
<>
<CryptoContextProvider>
<NewsContextProvider>
<DataContextProvider>{props.children}</DataContextProvider>
</NewsContextProvider>
</CryptoContextProvider>
</>
);
};
export default allContextProviders;
then i wrrap my app.js as follows
import allContextProviders from "./store/allContextProviders";
function App() {
return (
<allContextProviders>
<div className="App">
<Navbar />
<Routes>
<Route path="/" element={<Navigate to="/welcome" />} />
<Route path="/welcome" element={<Home />} />
<Route path="/marketplace" element={<Marketplace />} />
<Route path="/tools" element={<ToolsServices />} />
yet when i trie to wrap my app.js with the allContextProviders component i get this following error
Line 12:8: 'allContextProviders' is defined but never used no-unused-vars
am i doing something wrong here? your feedback is appreciated
In React to tell it that the variable name is Component ( and please evaluate it ), the name of the component should start with a capital letter like AllContextProvider. Please change it's name so that React knows and it will evaluate it in run time.

What is the proper way to do global state?

I have an app, and I want the app component to hold the current logged in user. I have the following routes and components.
Basically, every component in my app will make use of the user object. Sure, I can pass the user as props to each and every component, but that is not elegant. What is the proper React way of sharing the user prop globally?
const App = () => {
const [user, setUser] = useState(null);
return (
<Router>
<div className="app">
<Topbar />
<Switch>
<Route path="/login" exact component={Login} />
<Route path="/home" exact component={Home} />
<Route path="/" exact component={ShopMenu} />
<Route path="/orders">
<Orders />
</Route>
<Route path="/wishlist" exact component={Wishlist} />
<Route path="/wallet" exact component={Wallet} />
<Route path="/cart" exact component={Cart} />
</Switch>
<BottomBar />
</div>
</Router>
);
};
Take a look at React Context and more specifically useContext as you're using hooks.
The idea of context is exactly that - for you to be able to share updateable state to the descendants without having to pass it from component to component (the so called "prop-drilling").
export const UserContext = React.createContext(null);
const App = () => {
const [user, setUser] = useState(null);
return (
<Router>
<div className="app">
<UserContext.Provider value={{ user: user, setUser: setUser }}>
<Topbar />
<Switch>
{/* <routes>... */}
</Switch>
<BottomBar />
</UserContext.Provider>
</div>
</Router>
);
};
Then, in your component:
import { UserContext } from 'app';
const Topbar = () => {
const { user, setUser } = useContext(UserContext);
// use `user` here
};
If you want to have access to the setter (setUser) you can pass it through the context as well.
Simple React Global State with Hooks (Observer Design Pattern)
However "React way" was asked for, it might be helpful for all of you who seek for a simple and robust alternative.
codesandbox example
The concept is based on Yezy Ilomo's article. It just has been put into a working condition and been renamed the variables & functions to be more self-explaining.
I use it in production, in multiple projects, with this particular implementation directly (not Yezy's npm package) and it works like a charm.
Welcome to stack overflow;
Yes you can save your state globally for which react-redux library react offers in which you need to store your state globally and you can access state in any component from redux
here is the complete guide
You can also check
complete guide here of how to use redux with react
Also you can use context api
check here for context api

UseState inside routed functional components

I'm creating my first app with react-router and was having some trouble with an invalid hook error. I did manage to fix the error, but I don't really understand why this fixed it. So, in my App component I had a Switch with the following Route:
<Route
path="/signin"
exact
render={SignIn}
/>
Now lets suppose the SignIn component looked like this:
import React, { useState } from 'react';
const SignIn = () => {
const [test, setTest] = useState('test');
return (
<main>
{test}
</main>
)
}
export default SignIn;
With this set-up I kept getting an invalid hooks error, which only went away when I changed the Route in the App component to this:
<Route
path="/signin"
exact
render={(props) => <SignIn {...props}/>}
/>
Now this had solved the problem and the invalid hook problem went away, but why? I am not actually using any props in the SingIn component, at least not at the moment. Which of the React Hook Rules am I breaking here?
Since SignIn is a component, you can do it like this:
<Route
path="/signin"
exact
component={SignIn}
/>
The render syntax is when you want to pass some additional props

React Router with Loadable Components error

I've created a repository with a basic example that triggers this error in case it helps:
loadable-components-ssr
I'm trying to use Loadable Components in a SSR set up with react-router-dom 4.3.1, loadable-component 5.6.0 and react-dom 16.8.1
Here is a component example to which I'm trying to apply loadable-component:
import React from "react";
const About = () => <h2>About</h2>;
export default About;
This is imported in the App component like this:
import loadable from "#loadable/component";
...
const About = loadable(() => import("./About"));
And passed as a prop to Route in the same App component:
<Route path="/about/" component={About} />
But I keep getting the following warning in the Developer Tools console:
Warning: Failed prop type: Invalid prop component of type object supplied to Route, expected function
If I use an alternative syntax as suggested in the first answer:
<Route path="/about/" component={props => <About {...props} />} />
The warning disappears, but the route to /about still gives an error when the link is clicked:
Uncaught Error: Loading chunk About failed.
(missing: http://localhost:3000/about/About.bundle.js)
at HTMLScriptElement.onScriptComplete (VM1805 app.bundle.js:114)
I followed the documentation about setting up loadable-components in SSR, so I've set up the client, the server and also the babel plugin as indicated.
Any idea what's wrong here?
This is a known issue of react router.
I think that you could code the route like this:
<Route path="/about/" component={props => <About {...props} />} />
Be careful with this implementation, because you could have some buggy behaviours with the re-renders.
this is your "About" component:
import React from "react";
const About = () => <h2>About</h2>;
export default About;
you are not returning jsx. thats why you are getting error.
this is how you should have returned jsx.
const About = () => (<h2>About</h2>);
cheers!
why don't you use react.lazy? It is the official component.
const About = React.lazy(() => import('./About')
<Route exact path="/about" component={props => <About {...props} />} />

Resources