How to resolve an url by fetch & redirect without refresh with react - reactjs

I need to fetch the current url in my react application because our front/nginx may respond with a redirect which won't be hit if user has the service-worker active..
therefor I currently have this logic in my 404 component on didMount.
fetch('/test/page/xxxx/', {redirect: 'follow'}).then(res => {
if(res.status === 200 && res.redirected) {
console.log(res)
// this.props.push(res.url)
// window.location.replace(res.url)
// window.location.hash = res.url
console.log('Redirected to ' + res.url)
}
})
the res.url that I get back in the respons is a full url ex: https://example.net/xxx/xxx/xxxx which makes it hard for me to use push from react-router-redux because it expects a relative url. Can anyone help me with a regex that can get the slugs from the res.url or does anyone have any other idea how to solve this problem?

There is the URL interface [1] available in the window that can be used create a URL object.
A URL object has the pathname property that is used to retrieve the path component of the URL.
this.props.push(
new URL(res.url).pathname
)

The easiest way to get the pathname (relative URL) is by parsing it with the URL interface API
const { pathname } = new URL("https://example.net/aaa/bbb/ccc");
console.log(pathname) // "/aaa/bbb/ccc"
In the context of your code
fetch("/test/page/xxxx/", { redirect: "follow" }).then(res => {
if(res.status === 200 && res.redirected) {
const { pathname } = new URL(res.url);
this.props.push(pathname);
}
});
NOTE: Not supported in IE11 and below. If support for that browser is needed, there is a polyfill https://github.com/lifaon74/url-polyfill
There is also a proposal to be added to babel, expected soon to be a stage 0 feature

Related

How do I break the infinite redirect loop I've created in Next JS?

This application is being hosted on S3, entirely static (using next export), and we're routing all 404 errors to index.html in order to let those be handled on the client side so we can take advantage of dynamic routing. To handle this, I have the following in my _app.tsx file:
const { asPath, pathname, ...router } = useRouter();
// check if redirect
React.useEffect(() => {
if (pathname === '/' && asPath !== pathname) {
router.replace(asPath, undefined, { shallow: true });
}
}, [asPath]);
This works, for the dynamic routing aspect, but it introduces a new bug: when I navigate to a page that actually doesn't exist, like /fffff, there's an infinite loop of the app trying to reroute to /fffff. Ideally, it would only try to reroute once, and then default to the 404.tsx or _error.tsx page. I've tried creating a stateful boolean like hasRedirected and then just marking that as true in the useEffect, but that didn't work because the page is actually refreshing and thus resetting state on each router.replace call. How do I handle this error and break out of the loop?
update: The issue seems to be that when I call router.replace, Next doesn't find a path to match /fffff, so its default behavior is to try asking the server for the route by refreshing. I need to disable or intercept this behavior somehow.
The solution we ended up finding, which works quite well, uses session storage to store a hasRedirected variable that gets deleted after being read. Here's the code:
React.useEffect(() => {
if (router.isReady) {
const isRedirect = pathname === '/' && asPath !== pathname;
if (sessionStorage.getItem('hasRedirected')) {
sessionStorage.removeItem('hasRedirected');
if (isRedirect) router.replace('/404');
} else if (isRedirect) {
sessionStorage.setItem('hasRedirected', 'true');
router.replace(asPath);
}
}
}, [asPath, pathname, router.isReady]);

React URL param redirect

I am currently working with react and react-router and I'm building a page that shows details of a certain item that gets its data from an API when the page mounts. The fetch method requires the item's id so I'm using match.params.id to get the value for the fetch method. I also am using the slug package in the backend to show the title for that item in URL format alongside the id. I want users to be able to type in the URL with the slug title and not have to worry about typing the id in order to be directed to the page with the correct data.
For example, clicking on the item on the UI will make the URL look like this: localhost:3000/the-title-slug/123456.
You have to actually click on the item on the UI to get the URL to have the id but I want to make things simpler for the user and make it so that if they only type the slug title: localhost:3000/the-slug-title, it will redirect to the correct URL with that slug and id.
Any ideas on how this could be done? Kind of like if you type googel.com it corrects the typo and directs you to google.com. Any help figuring this out would be very appreciated, thank you.
Your backend must to have the API method to get correct item by misspelled slug.
like:
requestData: the-slug-title
responseData: the-title-slug, 123456
and then your component have to handle wrong url
componentDidMount() {
const { params } = this.props.match;
const respose = await fetch({ ... })
this.setState({ id: response.id, slug: response.slug });
}
render() {
const { params } = this.props.match;
return this.state.id && this.state.slug && (this.state.id !== params.id || this.state.slug !== params.slug) && <Redirect to={`/${this.state.slug}/${this.state.id}`} />
}

Localhost being prepended to Fetch request

I'm using a https url and for whatever reason fetch is adding localhost:300 to the start of the url. When I check the url that it's calling I get this: http://localhost:3000/%E2%80%8Bhttps://www... anybody know why?
// load API
componentDidMount() {
fetch('https://www.URL.com/api/route').then(res => {
return res.json()
}).then(data => {
this.setState({
orders : data
})
})
}
I encountered the same problem, and it was because I had a whitespace character in the beginning of the url before "https...". Perhaps you had a similar problem so fetch read the url as a relative path instead.
I had a similar problem in react application I was building. Mistyped URL was my mistake.

undefined in file path when trying to upload a file in React Application using ReactS3Uploader and SignedUrl

I am a newbie into React. I have been trying to upload file (images, json files etc) to AWS S3 bucket from a reactJS application using ReactS3Uploader (version 4.8.0). I am following this example : https://www.npmjs.com/package/react-s3-uploader
I have added the below code into one of my component where I want the file upload functionality :
<ReactS3Uploader
getSignedUrl={getSignedUrl}
accept="image/*"
s3path="/uploads/test/"
preprocess={this.onUploadStart}
onSignedUrl={this.onSignedUrl}
onProgress={this.onUploadProgress}
onError={this.onUploadError}
onFinish={this.onUploadFinish}
signingUrlHeaders={{ }}
signingUrlQueryParams={{ }}
signingUrlWithCredentials={ true } // in case when need to pass authentication credentials via CORS
uploadRequestHeaders={{ 'x-amz-acl': 'public-read' }} // this is the default
contentDisposition="auto"
scrubFilename={(filename) => filename.replace(/[^\w\d_\-.]+/ig, '')}
inputRef={cmp => this.uploadInput = cmp}
autoUpload={true}
server="http://cross-origin-server.com"
/>
I have also created another component for getSignedUrl (S3SignedUrl.js) as follows (as described here https://www.npmjs.com/package/react-s3-uploader ) :
import React, { Component } from 'react';
import { toast } from 'react-toastify';
import axios from '../../shared/axios';
function getSignedUrl(file, callback) {
console.log('.........Inside getSignedUrl()>>file.nameeeee.........'+file.name)
console.log('.........Inside getSignedUrl()>>file.size.........'+file.size)
const filename = file.name;
const params = {
filename: file.name
//contentType: file.type
};
var headers = {
'Content-Type': 'application/json'
}
axios.post(`/api/link/admin/v1/s3/sign?filename=${filename}`, {headers: headers})
.then(data => {
console.log('data.data.signedUrl>>>>>>>>>>>'+data.data.signedUrl)
callback(data);
return data.data
})
.catch(error => {
console.error(error);
});
}
export default getSignedUrl;
I have a groovy based backend api (springboot application) which creates the s3 signed url in the following format :
{
"signedUrl": “<complete signed url>”,
"uploadPath": “mybucket/apidocs/dev/version/logo/04137a9c-fb60-48dd-ae0f-c53d78e4e379/logo.png",
"expiresAt": 1552083549794
}
I am successfully able to call my groovy /s3/sign url from my react application through (S3SignedUrl.js which uses Axios) but right after that when ReactS3Uploader component tries to upload the file to the AWS S3 bucket, it gives me an error with HTTP 403.
When I see into the network tab (by inspecting within the google chrome), the underlying call being made my ReactS3Uploader component is
PUT https://localhost:3000/apps/gateway/undefined with Http 403
I am not sure what is undefined here within the url. Shouldn’t ReactS3Uploader component automatically be doing a HTTP PUT to the signedURL ?
I do see some fixes in react-s3-uploader version 4.6.2 around undefined in file path when not providing s3path property. https://changelogs.md/github/odysseyscience/react-s3-uploader/
But not sure if it has anything too do with the problem I am getting. By the way I am using using version 4.8.0.
Just to confirm I can successfully upload the file using that SignedURL manually thru curl.
Any help here would highly be appreciated.
Thanks in advance
I know this is an old post, but I've been searching for something similar and came across this.
You should have callback(data.data);.
ReactS3Uploader will redirect to an undefined URL if it's configured to use a getSignedUrl function and is not returned a signedUrl field.

admin-on-rest Using PATCH method

I am a junior node developer and am trying out admin on rest to quickly run up an admin panel for my json api. However, all of my update requests use patch instead of put. I attempted revising the UPDATE method in my restClient but this seems wrong (the rest of the methods are removed for brevity)
export default (apiUrl, httpClient = fetchJson) => {
const convertRESTRequestToHTTP = (type, resource, params) => {
let url = ''
const options = {}
switch (type) {
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`
options.method = 'PATCH'
options.body = JSON.stringify(params.data)
break
return { url, options }
}
}
To me this makes sense but when I try to edit an object I get back HTTP/1.1 404 Not Found <pre>Cannot PUT </pre>
I know that that this wasn't possible with previous versions but I read this https://marmelab.com/blog/2017/03/10/admin-on-rest-0-9.html#http-patch but was a little confused on how it works? I guess I just don't know where to start with this.
if problem still is actual now, please check some places which are using by me to set my customRestClient.
// App.js
import customRestClient from './customRestClient';
in my case i'm using httpClient to add custom headers:
import httpClient from './httpClient';
below:
const restClient = customRestClient('my_api_url', httpClient);
and finally:
<Admin title="Admin Panel" restClient={restClient}>

Resources