how can I use useRef to treat the div as textarea - html

I have a long message saved as html format. I want to show this message to the screen without Html element as textarea input.
message = <p>Mobil &auml ........ </p>
Before I upgrade React version to V6 it was working fine as the code below.
I could scroll down and adjust the textarea box size to see the message inside the box.
<div
id="textarea"
name="message"
className="form-control"
dangerouslySetInnerHTML={{__html: this.state.message }}
ref="textarea"
/>
after updating to React V6, when I write exactly the same code, it gives me an error saying
"Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here".
My first approach was to just simply delete ref="textarea" but then the message is overflow from the box and cannot read other information below.
And my second approach is to use useRef() but im not really understanding how to incorporate it to my code.
any suggestion here plz.

First option:
import { useEffect, useRef } from 'react';
function Teste() {
const divElement = useRef<HTMLDivElement>(null);
useEffect(() => {
if (divElement.current) {
divElement.current.appendChild(document.createElement('textarea')).value = 'Hello World';
}
});
return <div ref={divElement} />;
}
export default Teste;
Second option:
https://www.radix-ui.com/docs/primitives/utilities/slot

Related

Why does react not compile HTML present in a state

I set a default value of a state to be <b> Hey </b> . Now when I rendered this state on the UI it printed the string instead of Hey wrote in bold.I want to know why it is not working. Why react is not able to interpret the html tag and show the appropriate output
import { useState } from "react";
import "./styles.css";
export default function App() {
const [html, setHtml] = useState("<b>Hey</b>");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>{html}</div>
</div>
);
}
Output :-
Was expecting the output to be Hey written in bold.
Here's the codesandbox link for better understanding :- https://codesandbox.io/s/heuristic-chaum-vo6qt?file=/src/App.js
Thank you. I just want to know why react is not able to render the HTML tag as HTML tag instead of printing it out.
Because you are rendering a string, not HTML. If you want to render stringified HTML then use dangerouslySetInnerHTML, use caution what you pass through, in other words, you may want to run the string through a DOM purifier first.
export default function App() {
const [html, setHtml] = useState("<b>Hey</b>");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div dangerouslySetInnerHTML={{ __html: html}} />
</div>
);
}
You are setting the value of html as "<b>Hey</b>" which is a string string that's why it renders that as it is. You can directly assign html to the variable like so:
const [html, setHtml] = useState(<b>Hey</b>);
It's a string and not HTML, to fix that maybe you can insert it in the div as innerHTML ie.
document.querySelector(".divClassName").innerHTML = html

Problems with using InputMask PrimeVue in Vue3

Im trying to use InputMask from PrimeVue in project on Vue3
I have block in template tag:
<div class="sdf">
<label for="basic">Basic</label>
<InputMask mask="99-999999" v-model="val1" placeholder="99-999999" />
</div>
and i have script:
export default {
data: () => ({
val1: null,
})
}
Everything seems okay, and console doesn't show any errors, but still, input is not visible, only label is shown. What do i do wrong?
It sounds like you didn't register InputMask.
You could register it globally with app.component('InputMask', InputMask):
// main.js
const { createApp } = require('vue')
import PrimeVue from 'primevue/config'
import InputMask from 'primevue/inputmask'
import App from './App.vue'
createApp(App)
.use(PrimeVue)
.component('InputMask', InputMask)
.mount('#app')
demo

HTML components using Typescript, Knockout and Require - HTML is not rendered?

I am trying to learn how component driven development works and I have followed the documents here https://knockoutjs.com/documentation/component-custom-elements.html (Including the many nested links relevant to this topic) however although the TS/JS files are loaded without error the HTML component is never rendered.
Here you can see the the typescript is loaded correctly by RequireJS:
Login-User typescript loaded in browser
And here is the HTML component in the webpage:
HTML component
This is the content within the HTML 'template':
<div class="panel">
<label>Username:</label>
<input type="text" data-bind="Value: $component.Username()" />
<br />
<label>Password:</label>
<input type="text" data-bind="Value: $component.Password()" />
<br />
<label>Valid:</label>
<input type="text" data-bind="Value: $component.ValidUser()" />
</div>
Here is the registration of the HTML template:
const componentName = "Login-User";
ko.components.unregister(componentName);
ko.components.register(componentName, {
viewModel: LoginViewModel,
template: { require: `text!/Views/Components/${componentName}.html` }
});
I do not get any errors in the console but the constructor in the TS file is never hit when adding breakpoints to debug which suggests the me that there was no attempt to actually render the HTML component at all?
I have checked all file paths are correct and deleted and re-compiled the TS files to generate JS files to ensure everything is up to date, I assume I have not properly configured require in some way and so the HTML component is never actually registered however due to no errors being logged I am a bit stuck for where to go next! As I said previously I have read the documentation on Knockout and also for RequireJS however when searching google for issue when implementing a HTML component I seem to only get results for Angular.
Any advice on how to determine the issue would be greatly appreciated, even better if there is any documentation/guides on how to use Knockout/Require/Typescript/HTML Components together which someone could point me at that would be great!
I think I have provided everything need but if not let me know.
Thanks,
Danny
Okay after a couple more hours of trial and error I figured out I had a few problems, for anyone else having this issue try the below resolutions:
I was not calling ko.applybindings();
import * as ko from "knockout";
export default class LoginViewModel {
Username: KnockoutObservable<string>;
Password: KnockoutObservable<string>;
ValidUser: KnockoutComputed<boolean>;
constructor(username: string, password: string) {
this.Username = ko.observable(username);
this.Password = ko.observable(password);
this.computedMethods();
}
private computedMethods(): void {
this.ValidUser = ko.pureComputed(() => {
return this.Username() === "Danny" && this.Password() === "pasword";
});
}
}
const componentName = "login-user";
ko.components.register(componentName, {
viewModel: LoginViewModel,
template: { require: `text!Scripts/Typescript/${componentName}.html` }
});
ko.applyBindings(); << This is important as it actually binds the custom element i.e login-user params="username: 'Danny', password: 'none'"></login-user> and without it nothing will be rendered on the page
After correcting this issue I then got a 404 in console when trying to load the custom element and although the filepath was correct I found that the best way to resolve this was to have the custom element in the same folder as it's TS counter-part:
Before:
template: { require: `text!/Views/Components/${componentName}.html` }
After:
template: { require: `text!Scripts/Typescript/${componentName}.html` }
Google searches recommended installing the following nuget packages although I think only require.text is actually required, if it doesn't resolve your issue it's worth a shot..:
Require Packages
I initially had my components named using camel case i.e Login-User.ts and Login-User.html, I read somewhere that they should be lower case to be valid html 'Tags' and both the .ts and .html files should be named exactly the same
Hope this helps anyone else having issues.

reactjs dangerouslySetInnerHTML and dynamically adding classes to links

I'm new to reactjs and working on a project that is pushing json data to the template.
json structure
"description" : "Some text with a link and another link",
I propose using the following on the template
<p className='paragraph-margin-bottom-10 text--font-size-14 paragraph--justified' dangerouslySetInnerHTML={{ __html: lang.privacy[0].description }} />
but in terms of the output - I would maybe need to append a set of classes to ALL links. What is the best practice for this
so the links render with the following
<a class="text--font-size-14 hyperlink-primary" href="#">link</a>
I can imagine that many people will not agree with me. You can actually do this. But you shouldn't. It is bad enough that you want to use dangerouslySetInnerHTML. It is possible to parse html but there are many edge cases that you would need to handle.
Either tell your backend that they should return the links with proper classes or target the links inside the description directly with css.
See some similar question like: Using regular expressions to parse HTML: why not?
Using regular expressions to parse HTML: why not?
This is how I would do it. I will write the regex later if you run into some problems. I don't have much time to spare right now. Hope it will help. :)
import React from 'react';
import { render } from 'react-dom';
const htmlFromApi = 'some html from API'
const attachClassesToLinks = (htmlWithLinks) => {
// do something special
return htmlWithLinks
}
const App = () => (
<div>
<h1>My Component</h1>
<p dangerouslySetInnerHTML={{ __html: attachClassesToLinks(htmlFromApi) }} />
</div>
);
render(<App />, document.getElementById('root'));

How to get the HTML output from a rendered component

I am a newbie to the ReactJS world and trying to get into it. I am working on a style guide for which I need to display some HTML code as an example. I am using ReactPrism for that and I am not able to get the HTML output inside my PrismCode component, I have find a work around by using react-to-jsx which shows the JSX code instead of HTML.
This is the code:
import React from 'react';
import {PrismCode} from "react-prism";
import reactToJsx from 'react-to-jsx';
class CodePreview extends React.Component {
render (){
return (
<div>
{this.props.children}
<h5>Code example</h5>
<pre>
<PrismCode className="language-javascript">
{reactToJsx(this.props.children)}
</PrismCode>
</pre>
</div>
);
}
}
export default CodePreview;
So basically I want to render this.props.children (the component) as HTML code and not the content of it in the PrismCode
I even tried the following as shown on https://github.com/tomchentw/react-prism, but it doesn't work. Not sure what I am doing wrong!
<PrismCode className="language-javascript">
{require("raw-loader!./PrismCode")}
</PrismCode>
Have you considered writing your docs in markdown? I added some special tags for react:
```react:mirror
<Slider
value={7}
/>
```
This will show the rendered component and also the JSX syntax highlighted.
```react:demo
<PropsEditor>
<Slider
value={7}
/>
</PropsEditor>
```
This will render the component as well as a live editor to manipulate any props on the component.
```react
<SomeComponent />
```
Will just syntax highlight but not render the component.
At the top of my markdown file I can import any components I am using in the doc:
---
imports:
- import Slider from '../src/slider'
- import PropsEditor from 'props-editor'
---
The advantage of this way is that your docs work as normal markdown and it's easy to get the JSX as you have it as a string.
To get the HTML source I have a "View Source </> button which prints formatted html dynamically when clicked:
The steps are:
on click get the html of the react component
format the html using prism and a beautifier
insert it into the DOM
So wrap your react component and make a reference to the node:
<div ref={(n) => (this.fenceView = n)}>
And on click add the output below the component, relevant bits:
import prismjs from 'prismjs';
import beautify from 'xml-beautifier';
const RE_HTML_COMMENTS = /<!--[\s\S]*?-->/g;
removeCodeSource() {
const existingHtmlCode = this.fenceView.querySelector('.fence-generated-html');
if (existingHtmlCode) existingHtmlCode.remove();
}
renderCodeSource() {
const html = this.fenceView.children[0].innerHTML.replace(RE_HTML_COMMENTS, '');
const fenceCode = beautify(html, ' ');
const highlightedCode = prismjs.highlight(fenceCode, prismjs.languages.html);
this.removeCodeSource();
this.fenceView.insertAdjacentHTML('beforeend',
`<pre class="fence-generated-html language-html"><code>${highlightedCode}</code></pre>`);
}