Navigate with page reload using react router - javascript

My application uses a Laravel backend and a React frontend. Ordinarily, I would use e.preventDefault() so that there are no page reloads. The issue I am having is that if I login or logout without a page refresh, it causes a CSRF mismatch on future requests. So I'm okay with the page refresh. However, when I remove e.preventDefault(), the form data becomes appended to the URL. The best solution I have been able to come up with is this:
let csrfToken = document.head.querySelector('meta[name="csrf-token"]').content;
const navigate = useNavigate()
const handleLogin = async (e) => {
e.preventDefault()
axios.post('login', {email, password}, {
'X-CSRF-TOKEN': csrfToken
})
.then(() => {
setLoginStatus(true)
navigate('/')
window.location.reload();
})
}
This essentially works, but I don't like it. What happens is that the view is updated with the Component at '/,' and then the page refreshes. It just looks weird. All I want is for the Component at '/' to be rendered upon the form's submission with a page reload. Keeping in mind my problem with removing e.preventDefault(), where the form data gets added to the URL.

I couldn't realize this problem. But I think you can use useEffect and useState together.
For example: When the login operation finishes, set the data which will be gained to state. And make dependency with useEffect and that state. So if the state change the component automaticaly re-render beacuse of the useEffect. In this case no reload needed.

Related

Reflect changes without page refresh

I have created method to delete image as
action.js
export const removeImage = (id, image_id) => async () => {
try {
const response = await axios.delete(
`localhost:3000//api/v1/posts/${id}/delete/${image_id}`,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
)
I have call this method in post/[id].js as
<p onClick={() => removeImage(id, imgae.id)}>delete </p>
The problem is when I delete image I should hard refresh page to see changes. How can I solve this.
I have used useEffect hook
useEffect(()=> {
fetchData();
}, [data]);
It worked but load backend server too much.
Another idea I think to use useState hook. but how can I implement in this code?
Thanks in advance
I think that you try to do two different things :
Delete the image on your server with a request
Hide the image from your component / refresh your component src
You need to make the source image property of your component more reactive, like putting it in the state so you can modify it dynamically
Because here, you simply delete the resource on your server but your component is not refreshed or reloaded.
What you shoud do is to hide your component holding the image and display a kind of placeholder after clicking your delete button
Unless your app watches the server for updates you should manually reflect the changes you do on the server in your UI as well. For example, if you have a component, say an ImageButton, that is showing your image, and you remove the image from the server, what is the intended behavior? If you want the image button removed, you can simply set it’s visible property to false.

Router.push or Link not rendering/refreshing the page even thought the url is updated nextjs

I apologize for my horrendous way of explaining my issue. I have shared a link below description which is exactly the same issue I am experiencing. Any kind of help would be greatly appreciated.
I have directory path like pages/request/[reqid].js . When my url is localhost:3000/xyz and I navigate to pages/request/1 by clicking a button on the current page, the page successfully loads the page with proper data from [reqid=1] but when I try to access pages/request/[reqid].js with different reqid (say suppose reqid=2), the url reflects the correct the reqid pages/request/2 but the page remains the same, doesn't change. However if I go back to other pages like localhost:3000/xyz and click a button there to navigate to pages/request/2 it works but from within pages/request/[reqid] it doesn't render a page associated to the corresponding reqid even thought the url is updated. I have tried both Link and router.push ,both fails to render the correct reqid page.
https://github.com/vercel/next.js/issues/26270
It actually failed to include that I was using getServerProps to fetch the data, which was the reason the page wasn't rendering , unless the page was manually refreshed. The page state is not reset for navigation between dynamic routes that served by the same source component.
for example, give page source /a/[param]/index.js, when navigating from /test/123 to /test/124, states on the page wasn't being reset.
So actually happened is the same React Component been rendered with different props. Thus react takes it as a component is rerendering itself, and causing the new navigated page receive stale states.
To fix it, just add {key: } to page initial props or getserversideprops
export const getServerSideProps = async (ctx) => {
try {
const { reqid } = ctx.params;
//fetch code
return {
props: {
key: reqid,
data:data
},
};
} catch (error) {
console.log(error);
}
};

NextJS initial state is not updating when routing to same page with different params

This project is using NextJS
I have a page which URL looks like this
localhost:3000/first/second
I call getInitialProps on that page. Data is passed from getInitialProps to the component as it should be and I am setting initial state with that data like this
const Index = ({ data }) => {
const [state, setState] = useState(data.results)
}
Now when I send the user to
localhost:3000/first/third
getInitialprops is called as it should be. data, that is a parameter of component, is always populated with the latest results from getInitialProps but state isn't. It is populated with previous data that was in it. It is not resetting when I am doing client-side routing. Only when I hard refresh the page.
As suggested on NextJS GitHub I tired adding data.key = data.id, in ```getInitialProps``,` that is always a different number to force state update but it is not working.
Any info will be useful.
Thank you for your time :)
When using NextJS, getInitialProps is called before the page renders only for the first time. On subsequent page renders (client side routing), NextJS executes it on the client, but this means that data is not available before page render.
From the docs:
For the initial page load, getInitialProps will run on the server only. getInitialProps will then run on the client when navigating to a different route via the next/link component or by using next/router.
You would require a useEffect to sync state:
const Index = ({ data }) => {
const [state, setState] = useState(data.results);
useEffect(() => {
setState(data.results);
}, [data]);
}

Next.js, how to submit a form to another page?

(Next.js) I have a GET form on one page. I want to submit it to another page. I know I can set the action property to the other page. That works. However, it does a page reload instead of just rendering the new page; the same as would happen if you had a link on the page without wrapping it in a Link component.
I could catch the submit event, build a query, and push it onto the router. But that seems like a lot of extra work for something I assume has already been figured out.
Any ideas how to do this without reinventing the wheel?
<form method='get' action='/search'>
<input name='q' placeholder='Search' arial-label='Search' />
</form>
I ended up catching the submit event and pushing a URL onto the router.
import {useState} from 'react'
import {useRouter} from 'next/router'
const preventDefault = f => e => {
e.preventDefault()
f(e)
}
export default ({action = '/search'}) => {
const router = useRouter()
const [query, setQuery] = useState('')
const handleParam = setValue => e => setValue(e.target.value)
const handleSubmit = preventDefault(() => {
router.push({
pathname: action,
query: {q: query},
})
})
return (
<form onSubmit={handleSubmit}>
<input
type='text'
name='q'
value={query}
onChange={handleParam(setQuery)}
placeholder='Search'
aria-label='Search'
/>
</form>
)
}
Based on the Next.js' routing system and Router API:
The Next.js router allows you to do client-side route transitions between pages, similarly to a single-page application. A special React component called Link is provided to do this client-side route transition.
Router.push also handles client-side transitions, and this method is useful for cases where next/link is not enough.
So it seems that you can only perform client-side transitions by using any of those two ways.
Using the form above will trigger a behavior as described by MDN docs for a form submission, as none of the above rules applies:
...The server then responds, generally handling the data and loading the URL defined by the action attribute, causing a new page load (or a refresh of the existing page, if the action points to the same page).
I also found another reference close to your question in Next.js' issues board, where the preferred method to follow, was the one you've also described as a solution.

How to find Popup state and refresh state in React-router?

I know this question kind a stupid But I am pretty confused with this site producthunt how they are doing this.When clicking the product list popup with react router is done like this..
But When I refresh that page it render like this..How this is done using React-router
My bet would be that they use the state property when pushing a page to give an indication to the component about how to render the page. More specifically, to indicate the component where it comes from. For example:
router.push({
pathname: '/posts/origami-studio-by-facebook',
state: { fromPosts: true }
})
And then you can read the router's state in the route's component to check what page to show.
const Post = (productName) => {
if(this.context.router.location.state.fromPosts) {
return <Posts productPopup{productName} />
// open the posts page with a popup for the product
} else {
return <PostPage productName={productName} />
}
}
So when you open the page in your browser, the state.fromPosts is not set and you get redirected to the PostPage. In the end, even if the route is the same, what you end up seing is completely different.

Categories