I want to redirect users to Unprotected (login/ register) components if the user is not logged in (or verified) else allow access to Protected components.
To achieve that, I tried to use,
ProtectedRoute techniques
- PrivateRoute - failed to implement appropriately
- RequiresLogin - This helped me to reach to the next approach
- And some YouTube videos and articles found from Google
Code:
index.js
...
<Router>
<App />
</Router>
...
App.js - using the ProtectedRoute
...
<Routes>
<ProtectedRoute exact path={"page1"} element={<Page1 />}/>
<ProtectedRoute exact path={"page2"} element={<Page2 />}/>
<Route exact path={"login"} element={<Login />}/>
<Routes/>
...
RequireAuth
It seemed that it is a better approach then ProtectedRoute,
- RequireAuth - works except, it is ProtectiveOverflow at the moment
Code:
index.js
// Unchanged
App.js
...
<Routes>
<Route exact path={"page1"} element={
<RequireAuth>
<Page1 />
</RequireAuth>
}/>
<Route exact path={"page2"} element={
<RequireAuth>
<Page2 />
</RequireAuth>
}/>
<Route exact path={"login"} element={<Login />}/>
</Routes>
...
It seemed to work and I was able to protect the protected components. After implementing the authorization process, which I am doing by sending a fetch(...)
request to my API (djangorestframework) and getting the result dynamically everytime, I figured out that the protected components got a bit more protective than required. Now, although the server authenticating the request and sending sucessfull response, the protected pages are still locked.
Digging up, I realized that I have used the fetch function which is a Promise
and it runs on a separate thread. So, before the fetch could return the result, my component already gets rendered and unmounted.
Code:
RequireAuth.js
...
function RequireAuth({children}) {
const [auth, setAuth] = useState(false);
fetch(urls.auth, methods.get())
.then(r => r.json())
.then(data => {
setAuth(data)
})
.catch(error => {
console.log(error)
});
return auth? children : <Navigate to={"../login"}/>;
}
...
I have gone through various technique to solve this, for example,
Code:
RequireAuth.js
...
class RequireAuth extends React.Component {
constructor(props) {
super(props);
this.state = {auth: false}
fetch(urls.auth, methods.get())
.then(r => r.json())
.then(data => {
this.setState({auth: data})
})
.catch(error => {
console.log(error)
});
}
render() {
return this.state.auth? this.props.children : <Navigate to={"../login"}/>;
}
}
...
However, that failed too. Then I looked into,
- Fetch data and then render it to dom React
- Web Fetch API (waiting the fetch to complete and then executed the next instruction)
- Trying to implement a SIMPLE promise in Reactjs
- How to return data from promise
- How to get data returned from fetch() promise?
- How to finish all fetch before executing next function in React?
Finally,
I looked if I can do it using fetching or HttpRequest methods that does not run on different thread, but I afraid, even if it's possible, it can result in bad user experience. Therefore, please help me to solve this fetch authentication
issue in React. And, I would also like if there were other ways to implement the dynamic authorization using React
and djangorestframework
that could do this protective page stuffs more efficiently.
Thank you.