How to linkify hashtag in react - reactjs

I use the linkify-react module with the hashtag plugin
import Linkify from 'linkifyjs/react';
import * as linkify from 'linkifyjs';
import hashtag from 'linkifyjs/plugins/hashtag';
hashtag(linkify);
I'm not find any solution to let the hashtags links work directly in jsx component, it's possible?
<Linkify options={linkifyOptions} >{content}</Linkify>
in alternative I'm trying to use the plugin. Whit the plugin I retrieve an array of all hashtag in the content
const pTag = linkify.find(p.content || '');
// here the output
{
"type": "hashtag",
"value": "#tag",
"href": "#tag"
}
How I can replace all the hashtag with a link in the text? I've tried this solution but not works
pTag.forEach( (tag) => {
content.replace(tag, 'example.com/'+tag);
})

You can use formatHref property to add URL to each hashtag as per Linkify's documentation
https://soapbox.github.io/linkifyjs/docs/options.html
var linkifyOptions =
{
formatHref: function (href, type) {
if (type === 'hashtag') {
href = 'https://twitter.com/hashtag/' + href.substring(1);
}
return href;
}
}
var content = 'Linkify is #super #rad2015';
return <Linkify options={linkifyOptions}>{content}</Linkify>;
Checkout complete code here
https://codesandbox.io/s/linkify-sxt8c?fontsize=14

Related

Dynamic url rendered as a Document, api response. Angular

I'm using Django + Angular, and I have a dynamic url which works for first time when load my product page. I specified as a dynamic url in Django too, so the url look like this "product/home/:productName/:productId". Everything definitely works but as a response when I reload my page, it gets plain API response document. So, I compared the request details and when reload it gets document and angular pollifies not working. I was searching around didn't found anything.
url.py
path('product/home/<str:handle>/<int:id>', ProductGet)
view.py
#csrf_exempt
def ProductGet(request, handle, id):
product = Product.objects.get(id=id)
serializer = ProductSerializer(product, many=False)
return JsonResponse(serializer.data, safe=False)
So, this code works for first time, but then when I reload seems it changes host to Django and I'm getting as a response, my API response.
product-component.ts
ngOnInit(){
this.productService.data$.subscribe(res => this.update = res)
this.card = localStorage.getItem("card")
if(this.card === null){
this.card = null
}else {
this.card = JSON.parse(this.card)
}
this.router.params.subscribe((param:any)=> {
this.route = param.route
if(this.route === "home"){
this.route = {
route: "/",
name: "Основной"
}
}
console.log(param)
this.productService.getProduct(param.id, param.title).subscribe((res: any)=> {
this.product = res
this.selectedOption = res.options[0]
this.selectedOption.selectedOption = res.options[0].values[0]
this.selectedOptionName = res.options[0].values[0]
this.mainImg = this.host + res.image
this.isSale()
this.src1 = this.sanitizer.bypassSecurityTrustResourceUrl(this.product.specs.iframes[0].src)
this.src2 = this.sanitizer.bypassSecurityTrustResourceUrl(this.product.specs.iframes[1].src)
})
})
So, something with browser and framework host where angular didn't understand a request.So the fix.
app.module.ts
import {HashLocationStrategy, Location, LocationStrategy} from '#angular/common';
providers: [
{provide: LocationStrategy, useClass: HashLocationStrategy}
],

React Admin how to resolve an url into a field

I'm new with react admin and I'm tring to figure out how can I resolve an url in an Custom field. I am usin Django Rest Framework as my backend application and it returns this:
{
"id": "PwybRVej1r3L2Ag7smAvpqW45076GzZd",
"unity": "http://localhost:8000/api/v1/unity/n7VzbMW25rYZLB17SZ9Rl8eXqE36QDxk/",
"url": "http://localhost:8000/api/v1/truck/PwybRVej1r3L2Ag7smAvpqW45076GzZd/",
"created": "2022-08-08T23:48:32.876117Z",
"modified": "2022-08-08T23:48:32.876117Z",
"license_plate": "ADS-8974"
},
And I'm using JWT as the authentication standard. In this way I found ra-data-django-rest-framework. For simple cases, the usage is simply straightforward. But I'm trying to create a field that can resolve the url("http://localhost:8000/api/v1/unity/n7VzbMW25rYZLB17SZ9Rl8eXqE36QDxk/") and returns the information I need. Does anyone know how it could be resolved?
I tried this without success:
import * as React from "react";
import { useRecordContext, useGetOne } from 'react-admin';
const UnityField = ({ source }) => {
const record = useRecordContext();
const unity = useGetOne(record[source]);
console.log(unity)
return record ? (
<a href={record[source]}>
{unity}
</a>
) : null;
}
export default UnityField;
React-admin provides an <UrlField>, does it work in your case?
<UrlField source="unity" />
See https://marmelab.com/react-admin/UrlField.html for details

react-router generatePath with query parameters

I am using react-router's built in function generatePath to generate a URL. The issue is that as far as I understand this function just returns the path and doesn't provide a mechanism for us to know which fields were added in the path and which were not.
For example, for the following code
generatePath('/user/:id', {
id: 1,
name: 'John',
})
the function returns /user/1 which is correct, but there is no way for us to know that only id was inserted into the path and name needs to be passed as query parameters.
In my application both the path template and the params object are dynamic and I need to add the extra fields in params as the query parameters.
Is there any way to do that ?
For anyone checking now, I ended up using the path-to-regexp library which is the one used internally by react-router to generate the URL. The code looks something like this
import pathToRegexp from 'path-to-regexp';
import qs from 'qs';
const compiledCache = {};
export default function generatePathWithQueryParams(rawPath, params) {
let toPath;
if (compiledCache[rawPath]) {
toPath = compiledCache[rawPath];
} else {
toPath = pathToRegexp.compile(rawPath);
compiledCache[rawPath] = toPath;
}
const queryParams = { ...params };
const path = toPath(params, {
encode: (value, token) => {
delete queryParams[token.name];
return encodeURI(value);
},
});
const queryString = qs.stringify(queryParams);
if (queryString) {
return `${path}?${queryString}`;
}
return path;
};

How do I add a query param to Router.push in NextJS?

With NextJS, I'm trying to route to another page using an object that has a to and as field:
export const routes = {
'BrowseList' : {
'to' : '/apps/Browse/list',
'as' : '/browse/list'
}
// ....
}
and then that's imported and used like so:
import { routes } from './__routes';
import Router from 'next/router';
// ....
const { to, as } = routes.BrowseList;
Router.push(to, as);
which all works. My dilemma is that I'm trying to do something similar to this while attaching a query param. I'm trying to follow this example according to the docs:
Router.push({
pathname: '/about',
query: { name: 'Zeit' },
})
What I've tried (which doesn't work):
Router.push({
pathname : to,
as,
query : { user_id: this.props.data.member.user.id },
});
which gives me a console warning of
Unknown key passed via urlObject into url.format: as
I know I can maybe possibly just use string interpolation and do something like this:
Router.push(to, `${as}?user_id=`${this.props.data.member.user.id}`)
but I was wondering if there was something I'm missing in the doc's example that also adds the query param into my as value.
Thank you.
You were close #nyphur. The as value goes as the second parameter of push and not inside the object that corresponds to to (check router.d.ts to see how push is defined). That's why you're getting the error Unknown key passed via urlObject into url.format: as. After 10 months from your question maybe this could still be useful to someone looking for an answer. Assuming you have a way to build the query string for the as parameter, following #Gezim answer or by any other approach:
Router.push({ pathname: to, query: { user_id: this.props.data.member.user.id } }, as, options);
NOTE: Based on #Gezim answer, if you format the string or pathname in the first parameter to contain your query params, it'll work BUT encoded values, if any, like %2B for instance will be decoded so you will get +. This doesn't happen if the query params object go inside query. Consider this if you have any kind of logic that depends on this.
It appears that the router in next.js doesn't have any convenient API to navigate to using a query string.
I created a utility class called LinkCreator with a toQuery method as follows. It uses query-string to create the query string:
import * as qs from 'query-string';
export class LinkCreator {
static query(object) {
return qs.stringify(object);
}
static toQuery(object, path = "/") {
const query = this.query(object);
return path + '?' + query;
}
}
Then, it can be used with Router.push like so:
Router.push(LinkCreator.toQuery({ name: 'Zeit' }), '/about');
Edit: at first I thought merging an object via spreading would be an easy fix, but then as a comment pointed out there needed to be some changes, so I have updated my answer to still utilize spreading, but unfortunately it does now make the Routes more complicated and involved, but the consumption of it is still straight forward.
I would also freeze the Routes object for peace of mind as well.
import Router from 'next/router';
export const Routes = Object.freeze({
BrowseList(query) {
return [
{
pathname: '/apps/Browse/list',
query
},
'/browse/list'
]
}
// ....
})
Router.push(
...Routes.BrowseList({
paramName: "Param value here"
})
)
Additional Abstraction
import Router from 'next/router';
const QueryRoutePath = (to, as, query) => ([
{
pathname: to,
query
},
as
])
export const Routes = Object.freeze({
BrowseList(query) {
return QueryRoutePath(
'/apps/Browse/list',
'/browse/list',
query)
}
// ....
})
const query = {
paramName: "Param value here"
}
Router.push(
...Routes.BrowseList(query)
)

How to replace HTML images with GatsbyJS responsive images?

I am querying data from the Directus CMS in GatsbyJS using the Directus 7 source like so:
query {
allDirectusBlog {
edges {
node {
name
body
}
}
}
}
My problem is that body is actually raw HTML with image tags pointing to my Directus server. Which is normally fine, however these images are extremely large and take a fair amount of time to load even over WiFi. Is there a way to replace these <img> tags with Gatsby responsive images at build time?
I've create a function using html-react-parser with the post content of WordPress to replace all img with of Gatsby and the image provide in the static folder.
If you want a way to do that, this is a part of my code that you'll be able to adapte for your project (this is a WIP function, but work well)
export const ParsePostContentHTML = dataContent => {
let indexKeyImg = 234;
const ParsedHTML = Parse(dataContent, {
replace: function(domNode) {
if(domNode.name === 'img') {
const fluidImg = data.allWordpressWpMedia.edges.filter(media => {
return media.node.source_url === domNode.attribs.src
})
if(fluidImg.length > 0) {
let srcMedia = (fluidImg[0].node.localFile.childImageSharp)
? fluidImg[0].node.localFile.childImageSharp.fluid
: fluidImg[0].node.localFile.publicURL
indexKeyImg++
if(fluidImg[0].node.localFile.childImageSharp) {
return (
<Img
key={indexKeyImg}
fluid={srcMedia}
className={`${domNode.attribs.class} gatsby-rendered-img`}
alt={fluidImg[0].node.alt_text}
/>
)
} else {
return (
<img
key={indexKeyImg}
src={srcMedia}
className={`${domNode.attribs.class} gatsby-rendered-img`}
alt={fluidImg[0].node.alt_text}
/>
)
}
}
}
}
})
return ParsedHTML
}
You just have to import this function in your components/template and using it with ParsePostContentHTML(YourPostContent)
Hope that help you!

Resources