Different output when passing string by props and using a const value - javascript

I want to pass text to my react component using props. The important thing is I need the new line symbol ("\n") to work.
My example is very simple:
class UnderlinedText extends React.Component {
render() {
const text = 'Hello\n this is a test'; // this works
// const text = this.props.text; this does NOT work
return (
<div className="textContainer">{text}</div>
);
}
}
ReactDOM.render(
<UnderlinedText />,
document.getElementById("root")
);
.textContainer {
white-space: pre-line;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Using the hardcoded text above everything works as it should (even in debug I see that the string spans in multiple lines). But using it via props like so:
class UnderlinedText extends React.Component {
render() {
const text = this.props.text;
return (
<div className="textContainer">{text}</div>
);
}
}
ReactDOM.render(
<UnderlinedText text='Hello\n this is a test' />,
document.getElementById("root")
);
.textContainer {
white-space: pre-line;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
does not create the new lines and the string in debug has all the new line symbols ("\n") in it.
Where is the difference between those two solutions? And how to solve it?

Because you're using a literal string in
<UnderlinedText text='Hello\n this is a test' />
React is treating it as literal text. \n is \ and n, just like it would be in an HTML attribute.
If you want to supply a JavaScript string with JavaScript escape sequences in it, use {} around it to switch to a JavaScript expression context:
<UnderlinedText text={'Hello\n this is a test'} />
Live Example:
class UnderlinedText extends React.Component {
render() {
const text = this.props.text;
return (
<div className="textContainer">{text}</div>
);
}
}
ReactDOM.render(
<UnderlinedText text={'Hello\n this is a test'} />,
document.getElementById("root")
);
.textContainer {
white-space: pre-line;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

How to edit css modules in react

I have the following files:
Test.js:
import React from 'react';
import style from './style.module.css'
function Test() {
return(<div className={style.classcolor}>Test</div>);
}
export default Test;
style.module.css
.classcolor
{
background-color:blue;
}
Is there a way to change the css attributes inside the js file, similar to the code below?
style.classcolor.backgroundColor ="red";
An option is to use a variable and change the class depending on it:
class Test extends React.Component {
constructor(props) {
super(props);
this.state = { orange: true }
}
toggleClass = () => {
this.setState({ orange: !this.state.orange })
}
render() {
const { orange } = this.state
return (
<div>
<div className={orange ? 'orange' : 'red'}>Test</div>
<button onClick={this.toggleClass}>Toggle class</button>
</div>
);
}
}
ReactDOM.render(
<Test />,
document.getElementById("react")
);
.orange{
color: orange;
}
.red{
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
A not really react way is to use element.style, more information:
document.getElementById('test').style.color = 'orange';
<div id="test">Test</div>
you can add array [0] after get the className, and then you can access the style from DOM
document.getElementsByClassName(style.classcolor)[0].style.backgroundColor = 'red'
You can see this library styled-component, you can pass props for the component and by the value of the prop, you decide in how the style will be.

How to make script type both text/babel and module?

It works perfectly because I haven't included JSX, but when I replace the script type with text/babel, it doesn't work because the module fails to load. browser.js the Babel compiler.
Here... JSX works only when i replace script type with text/babel but the problem is module fails to load since the script is not module. Any idea how make it work with JSX?
<div id="root">
</div>
<script type="module">
import './react.min.js';
import './react-dom.min.js';
import './browser.js';
class Hello extends React.Component {
render() {
return React.createElement('div', null, `Hello ${this.props.toWhat}`);
}
}
ReactDOM.render(
React.createElement(Hello, {toWhat: 'World'}, null),
document.getElementById('root')
);
</script>
UPDATE July 2021
As per mh sattarian's answer you now don't need data-plugins="transform-es2015-modules-umd" to use native es6 module's import/export etc. Instead you simply add data-type="module"
Original Answer
Just in case if some one comes here looking for answer
There is a support for data-plugins and data-presets in babel standalone
<script data-plugins="transform-es2015-modules-umd" type="text/babel">
see more here
Babel standalone
As mentioned in the docs, it's added in: v7.10.0.
If you want to use your browser's native support for ES Modules, you'd
normally need to set a type="module" attribute on your script tag.
With #babel/standalone, set a data-type="module" attribute instead,
like this:
<script type="text/babel" data-type="module">
I think the question was if it is possible to use a script tag with two or more types at the same time (e.g. something like type="module, txt/babel"). As far as I know the answer is NO.
JonDotsoy's answer helps with reduce typing React.createElement over and over again but even with such a "variable shortcut" it's not as comfortable as JSX when using larger templates with nested elements because h('div', {}, 'hello!!')... is difficult to maintain in such cases.
The only way I found to combine native browser module support and in-browser Babel for JSX without using any build tool is this ... a rather dirty hack that uses eval and should not be used for production apps:
index.html
<body>
<div id="app"></div>
<!-- Scripts ------- -->
<script src="vendor/js/babel.min.js"></script>
<script src="vendor/js/react.development.js"></script>
<script src="vendor/js/react-dom.development.js"></script>
<script src="app/app.js" type="module"></script>
</body>
app/app.js
import ComponentOne from "./ComponentOne.js";
let template = `
<div>
<h1>Heading</h1>
<hr />
<ComponentOne msg="MsgText-ComponentOne" />
</div>
`;
const App = () => {
return (
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
ReactDOM.render(
React.createElement(App, null),
document.getElementById("app")
);
app/ComponentOne.js
import ComponentTwo from "./ComponentTwo.js";
let template = `
<div>
<h2>This is ComponentOne</h2>
<p key="2">Property "msg" content: {props.msg}</p>
<ComponentTwo msg="MsgText-ComponentTwo" />
</div>
`;
const ComponentOne = (props) => {
return(
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
export default ComponentOne;
app/ComponentTwo.js
let template = `
<div>
<h2>This is ComponentTwo</h2>
<p key="2">Property "msg" content: {props.msg}</p>
</div>
`;
const ComponentTwo = (props) => {
return(
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
export default ComponentTwo;
you may prefer to use an alias to createElement. This way is faster for the engine.
For example use h or e.
const { createElement: h } = React;
const App = () => {
return h('div', {}, 'hello!!');
}
Otherwise, it is possible to use #babel/standalone module, please see more on here https://babeljs.io/docs/en/next/babel-standalone.html.
<div id="app"></div>
<!-- Load Babel -->
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<!-- Your custom script here -->
<script type="text/babel">
const { render } = ReactDOM;
const App = () => {
return <div>hello!!</div>
}
render(<App />, document.getElementById('app'));
</script>

Injecting dynamic HTML in React - CSS is not working

Fetching dynamic HTML from an API, the HTML is loading fine but the CSS is not working for this new HTML.
Do you I need to reload the CSS.
import React, { Component } from "react";
import Utility from "../common/Utility";
class Template extends Component {
constructor(props) {
super(props);
this.token = localStorage.getItem("token");
this.client_id = localStorage.getItem("client_id");
}
componentDidMount() {
//fetching dynamic html
Utility.ExecuteData("template", this.token, {
client_id: this.client_id
}).then(result => {
var dynamic_html = document.getElementById("dynamic_html");
dynamic_html.innerHTML = result.data[0].template;
});
}
render() {
return (
<React.Fragment>
<div id="dynamic_html" />
</React.Fragment>
);
}
}
export default Template;
It is possible to get this to work but instead of className you'll need to use the usual HTML class attribute. I've used dangerouslySetInnerHTML here, but it's the same result if you set the innerHTML of the element like you did in your question.
function Template({ html }) {
return (
<div dangerouslySetInnerHTML={{__html: html}} />
);
}
const html = '<div class="heading">With style</div>';
ReactDOM.render(
<Template html={html} />,
document.getElementById('container')
);
.heading {
font-size: 2em;
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>
I can't comment so I'm posting it in an answer instead.
I don't know how the html is being returned from the API but I assume the css is either inlined or included as a file in the remote HTML.
If the latter is the case, it might be a possibility that the url to the css file is relative, so calling the url from another server would result in a 404.

How to pass props stated in HTML to root component

I'm using a simple component in React for two buttons in an existing HTML/JavaScript, (not a React project) project. It looks like this:
//Submitcancel.jsx
'use strict'
class Submitcancel extends React.Component {
constructor(props) {
super(props)
console.log(props)
}
render() {
return (
<div className="form-buttons">
<div className="ibm-col-12-12">
<button id="buttonSubmit" name="buttonSubmit" value="Submit" type="submit" className="ibm-btn-pri dw-btn-blue">Submit</button>
<button value="Cancel" id="buttonCancel" name="buttonCancel" className="ibm-btn-sec dw-btn-blue">Cancel</button>
</div>
</div>
)
}
}
ReactDOM.render(
// React.createElement(Submitcancel),
// document.querySelector('#react-submit-cancel')
)
The HTML file looks like this:
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<!-- Load React component. -->
<script type="text/babel" src="./js/components/Submitcancel.jsx"></script>
The component element where I would like to define the props is like this:
<div id="react-submit-cancel"></div>
If you want to grab the button texts from your HTML <div>, you need a non-react solution for that:
<div id="react-submit-cancel" submitText="Go"></div>
then in your initialization:
const el = document.querySelector('#react-submit-cancel');
const props = {
submitText: el.getAttribute("submitText") || "Submit", // default value
cancelText: el.getAttribute("cancelText") || "Cancel"
};
ReactDOM.render(React.createElement(Submitcancel, props), el)
For a pure React solution you'd have to wrap the Submitcancel component so you can pass props to it using JSX.
When you need to pass data through props, you just need to mention props id and value along with component.
In your case code will be like:
ReactDOM.render(
<Submitcancel FirstName={"first name"} LastName={"last name"}/>,
document.getElementById("react-submit-cancel")
)
Above example FirstName and LastName are two props
You can get the value in constructor inside the Submitcancel component.
constructor(props) {
super(props)
console.log(props.FirstName)
console.log(props.LastName)
}
Please follow this code:
ReactDOM.render(
<Submitcancel />,
document.getElementById("react-submit-cancel")
)

How to import js file in react component?

$( "#left_arrow" ).click(function() {
if ($(".left_block").hasClass("w-0")) {
$(".left_block" ).removeClass("w-0");
}else{
$(".left_block" ).addClass("w-0");
}
});
In the custom.js I am having the script code above feature is not working when importing with below.
import * as script from '../js/custom.js';
In the Html page when I load this file its working but when writing in react component its not working
You should not mix with jquery with React, What you want to achieve can easily be implemented in React like
class App extends React.Component {
state = {
class: 'w-0'
}
handleClick=()=> {
if(this.state.class === 'w-0') {
this.setState({class: ''})
} else{
this.setState({class: 'w-0'})
}
}
render() {
return (
<div>
<div id="left_arrow" className="left_arrow" onClick={this.handleClick}><i className="fa fa-chevron-left" />Arrow</div>
<div className={"left_block " + this.state.class}>Hello World</div>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

Categories