ReactJS highlight blog post that comes from the server - reactjs

I've been trying to use highlight.js with my react project , but it never worked.
I have a blog, and for each post I fetch the post data from the server.
Unfortunately - highlight.js does not work properly when it comes to dynamic data and async proccess.
Lets say we have this code that i fetch:
bla blba blahbla blba blahbla blba blahbla blba blah...
<code><div class="test"></div></code>
bbla blba blah....
So , I did try to import highlight.js with the css theme, and used hljs.highlightAll() , but it didn't work properly.
Maybe there is some other solution \ library where I can highlight the code?
What's the alternative?
thank you.
import { React, useEffect } from "react";
import { useParams } from "react-router-dom";
import hljs from "../../node_modules/highlight.js/lib/core";
import "../../node_modules/highlight.js/styles/arta.css";
import "./BlogPost.css";
function BlogPost(props) {
hljs.initHighlightingOnLoad();
const updateCodeSyntaxHighlighting = () => {
document.querySelectorAll("code").forEach((block) => {
hljs.highlightBlock(block);
});
};
useEffect(() => {
getPostData();
updateCodeSyntaxHighlighting();
}, []);
// GetPostDataById(id);
return <div dangerouslySetInnerHTML={{ __html: postData }}></div>;
}
export default BlogPost;
result:
as you can see - the background gets darker , but not really highlighted text.

Your not importing the entire highlight.js library so you can just do import hljs from 'highlight.js' instead of going into the node modules folder to get it. Also you are not specifying the language you want to highlight in with the class of the code block. In the example I am just going to hard code the postData with class='language-javascript' for the <code> block to get the correct syntax highlighting. So here is a working example:
Working Codesandbox
import { React, useEffect } from 'react'
import hljs from 'highlight.js'
import '../../node_modules/highlight.js/styles/arta.css'
const postData = `<pre><code class="language-javascript">console.log('hello');</code></pre>`
function BlogPost(props) {
const updateCodeSyntaxHighlighting = () => {
document.querySelectorAll('code').forEach((block) => {
hljs.highlightElement(block)
})
}
useEffect(() => {
updateCodeSyntaxHighlighting()
}, [])
// GetPostDataById(id);
return <div dangerouslySetInnerHTML={{ __html: postData }}></div>
}

Related

Trying to add anime.js in react but not working

I am trying to implement animejs in my react projects. But unable to run my first code. I already installed my animejs package. It would be great if you would help me learn this and guide me on how to do it. Here is the code, help me to resolve the error.
import {useEffect} from 'react'
import anime from 'animejs/lib/anime.es.js';
// import { easings } from 'animejs';
export default function Homeanime() {
const fontSize = {
fontSize:'40px'
}
useEffect(() => {
const basicTimeline = anime.timeline({autoplay:true})
basicTimeline
.add({
target:'.check',
translateX: 250
})
},[])
return (
<>
<h1 className='p-5 check' style={fontSize}>Working</h1>
</>
)
}

The order of hooks issue with React and I18n

I am working on a small project where I created a provider to change the language from Arabic to English and vice versa. Here is how it looks:
import React from "react";
import { useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
const LanguageProvider = ({ children }) => {
const lang = useSelector((state) => state.LanguageReducer);
const { i18n } = useTranslation();
React.useEffect(() => {
if (i18n.changeLanguage) i18n.changeLanguage(lang.language);
}, [i18n, lang]);
return <div {...{ dir: lang.activeDir }}>{children}</div>;
};
export default LanguageProvider;
And I wrap my app with this provide along with the context provider. But I face this issue when the home page of the project loads and I cannot solve it so far.
React has detected a change in the order of Hooks called by LanguageProvider. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks
What could the problem be here?

install quilljs-markdown on react

I need such an editor on react https://cloverhearts.github.io/quilljs-markdown/ , as you can see in it you can put markdown characters directly into the text.
when I do this
import React, { Component } from 'react'
import './App.css'
import ReactQuill from 'react-quill'
import Quill from 'quill'
import QuillMarkdown from 'quilljs-markdown'
const App = () => {
const editor = new Quill('#editor', {
theme: 'snow'
})
new QuillMarkdown(editor)
return (
<div className='app'>
{/*<MyComponent/>*/}
<div id="editor"></div>
</div>
)
}
export default App
I get error TypeError: Cannot read property 'on' of undefined
as I understand I need jQuery for work, but I use react, I found https://www.npmjs.com/package/react-quill this quilljs for react, but I don't know how to combine it with markdown https://www.npmjs.com/package/quilljs-markdown
can anyone help?
I found the solution for this after hours of trying this out.
What you have to do is this:
Create a module for ReactQuill
Register the module.
Pass modules to react quill
Shown Below.
Step 01
const modules = {
markdownOptions: {}
};
Step 02
Quill.register('modules/markdownOptions', QuillMarkdown);
Step 03
<ReactQuill
modules={modules}
/>
It seems like you are trying to initialize the Quill instance and the markdown module before the editor is ready.
Use useEffect hook to initialize it after the div has been rendered:
import {useEffect} from 'react';
...
useEffect(() => {
const editor = new Quill('#editor', {
theme: 'snow'
});
new QuillMarkdown(editor);
});

How do I add an event listener to a React component?

I'm trying to build a React web app (v 16.13.0). I want a flash message component, to display status after a form is submitted. If there is already something standard, that would be preferable, but since I can't find anything, I'm trying to roll my own using this -- https://medium.com/#jaouad_45834/building-a-flash-message-component-with-react-js-6288da386d53 . Here's the component
import React, { useEffect, useState } from 'react';
import Bus from '../Utils/Bus';
import './index.css';
export const Flash = () => {
let [visibility, setVisibility] = useState(false);
let [message, setMessage] = useState('');
let [type, setType] = useState('');
useEffect(() => {
Bus.addListener('flash', ({message, type}) => {
setVisibility(true);
setMessage(message);
setType(type);
setTimeout(() => {
setVisibility(false);
}, 4000);
});
}, []);
useEffect(() => {
if(document.querySelector('.close') !== null) {
document.
querySelector('.close').
addEventListener('click', () => setVisibility(false));
}
})
return (
visibility && <div className={`alert alert-${type}`}>
<span className="close"><strong>X</strong></span>
<p>{message}</p>
</div>
)
}
Problem is, web site uses custom code, but doesn't show source for
Bus.addListener('flash', ({message, type}) => {
setVisibility(true);
setMessage(message);
setType(type);
setTimeout(() => {
setVisibility(false);
}, 4000);
});
so my question is, how do I add an event listener to a React component?
Edit: In response to the answer given, I created this file ...
localhost:client davea$ cat src/Utils/Bus.js
import EventEmitter from 'events';
export default new EventEmitter();
but re-compiling my module results in this error ...
./src/components/Flash/index.js
Module not found: Can't resolve '../Utils/Bus' in '/Users/davea/Documents/workspace/chicommons/maps/client/src/components/Flash'
These are the first lines of the file above. Note the second "import" where I'm importing "Bus" ...
import React, { useEffect, useState } from 'react';
import Bus from '../Utils/Bus';
import './index.css';
export const Flash = () => {
The website included the code: https://medium.com/#jaouad_45834/building-a-flash-message-component-with-react-js-6288da386d53
To set that up, we need to create a new folder in our root directory and name it Utils and create on it a Bus.js file with will contains the following code:
import EventEmitter from 'events';
export default new EventEmitter();
This is all Bus.js is, a simple event emitter.
You can also use react-toastify or useToasts for this.
In order to show the flash message, you need to do something like the following.
Bus.emit('flash', {type: 'danger', message: 'error occurred'});
I have used the code you have provided and mixed it with a dummy form. Upon submitting the form, the flash message appears successfully.
Live example & working code is here:
https://codesandbox.io/s/dazzling-lamarr-k3cn5
Some notes:
I have refactored and removed 2nd useEffect as it is inefficient and unnecessary. The onClick can very well be applied to the close-span-element
If you are using redux, you can use create global Flash/Alert message and connect it to the store. Any redux-connected-component can simply work its own logic and dispatch an alert action and render different types of messages.
Using ready made libraries are also cool.
I think what you want is widely known as a Toaster, and you can use a library like React Toastify [https://github.com/fkhadra/react-toastify] with a simple configuration and high customization

Using marked in react

I want to use marked in reactjs as described in the reactjs docs.
<div>{marked(mystring)}</div>
I use babel so I import marked like this:
import { marked } from 'marked';
Unfortunately the import statement does not work. marked is not defined.
How do I have to import marked here, so that I can use it?
Here's one way to use marked with React:
Ensure that you've installed marked
Include marked in your project's package.json file:
// package.json
{
dependencies: {
react: "^17.0.0",
marked: "^4.0.0",
},
}
Import marked in your .jsx (or related) file:
import { marked } from "marked";
Use the dangerouslySetInnerHTML approach as shown in the example below:
import React from "react";
import { marked } from "marked";
class MarkdownExample extends React.Component {
getMarkdownText() {
var rawMarkup = marked.parse("This is _Markdown_.");
return { __html: rawMarkup };
}
render() {
return <div dangerouslySetInnerHTML={this.getMarkdownText()} />;
}
}
The dangerouslySetInnerHTML attribute gives you the ability to work with raw (HTML) markup. Make sure to take care when using this attribute, though!
Alternative (Safe)
If you don't want to use dangerouslySetInnerHTML and safely render HTML. Try marked-react, which internally uses marked to render the html elements as react components
npm i marked-react
import Markdown from "marked-react";
const MarkdownComponent = () => {
return <Markdown>{rawmarkdown}</Markdown>;
};
Another alternative is react-markdown
Here is another way of using marked with React Hooks:
Create your MarkedConverter component
import { useState } from 'react'
import marked from 'marked'
export const MarkedConverter = () => {
const [markedVal, setMarkedVal] = useState(
'# Welcome to my React Markdown Previewer!'
)
return <div dangerouslySetInnerHTML={createMarkUp(markedVal)}></div>
}
Create Markup function and pass the value from MarkedConverter Component
export const createMarkUp = (val) => {
return { __html: marked(val) }
}
Finally you can import MarkedConverter Component to any of your Component
With the marked-wrapper react-marked-markdown:
import { MarkdownPreview } from 'react-marked-markdown'
export default ({ post }) => (
<div>
<h1>{ post.title }</h1>
<MarkdownPreview value={ post.content }/>
</div>
)
If you just want to import marked:
import marked from 'marked';
Then call the function in your component:
marked('# Markdown');
Here's an example on how to use marked with react:
Install marked with NPM : npm i marked
import it in your react app (this example is created with create-react-app), and using it
example of a react component using "marked"
result in the browser :
preview

Resources