I'm trying to render the message with html tags inside it. The rendering is working fine if the string is passed as prop, but when the same is passed from a variable the display text has encoded text.
Any idea how do I get it working in both scenarios.?
class Hello extends React.Component {
render() {
console.log(this.props.name)
return <div>{this.props.name}</div>;
}
}
ReactDOM.render(
<Hello name="<p>How are you?</p>" />,
document.getElementById('container') --> **<p>How are you?</p>**
);
class HelloOther extends React.Component {
render() {
const name = "<p>How are you?</p>"
return <Hello name={name} />;
}
}
ReactDOM.render(
<HelloOther />,
document.getElementById('container2') -- <p>How are you?</p> -- > why?
);
Fiddle link - https://jsfiddle.net/d6s7be1f/2/
class Hello extends React.Component {
createMarkup() {
return {__html: this.props.name};
}
render() {
return <div dangerouslySetInnerHTML={this.createMarkup()} />;
}
}
From React Docs:
In general, setting HTML from code is risky because it’s easy to
inadvertently expose your users to a cross-site scripting (XSS)
attack. So, you can set HTML directly from React, but you have to type
out dangerouslySetInnerHTML and pass an object with a __html key, to
remind yourself that it’s dangerous.
Unless you want to use dangerouslySetInnerHTML, you could use a regex to wrap the string with html tags. This way, you don't have to pass html entities in the string. You just pass the string and wrap the string with html tag using .replace() function.
Since you also want the string to be parsed as HTML, you could pass an extra prop to the Hello component that is then used to wrap the string with the desired html tag and also render the string nested within the desired html tag
function HTMLTag({ tag, children }) {
return React.createElement(tag, null, children);
}
class Hello extends React.Component {
render() {
const { name, tag } = this.props;
const str = name.replace(/(.+)/, `<${tag}>$1</${tag}>`);
return (
<div>
<HTMLTag tag={tag}>{str}</HTMLTag>
</div>
);
}
}
class HelloOther extends React.Component {
render() {
const name = "How are you?";
return <Hello name={name} tag="h3" />;
}
}
ReactDOM.render(
<Hello name="How are you?" tag="p" />,
document.getElementById('container')
);
ReactDOM.render(
<HelloOther />,
document.getElementById('container2')
);
<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>
<div id="container2"></div>
Related
I want to get the text content of the react element. In the example below, I want get: hello 1
var node = <myComponent id={1} />
class myComponent extends React.Component {
render() {
return {
<span> hello {this.props.id} </span>
}
}
I tried to use node.text or ReactDOM.findDOMNode(node).textContent, but it doesn't work. Can I get some help?
Thanks!
Hi i think you should modify your code like below :
<myComponent id={1} />
Try calling your code using:
ReactDOM.render(<MyComponent id={1} />, document.getElementById("root"));
Your code:
class MyComponent extends React.Component {
render() {
return <span>Hello {this.props.id}</span>;
}
}
Link to this code in a Codesandbox:
https://codesandbox.io/s/class-component-dv6fj
I'm new to react and am trying to implement a simple for loop, as demonstrated in this other stackoverflow post. However, I cannot seem to make it work. I just want to run the component 5 (or any number of) times rather than map over an array or similar.
DEMO: https://stackblitz.com/edit/react-ekmvak
Take this example here:
index.js:
import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
import Test from './test';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
for (var i=0; i < 5; i++) {
<Test />
}
</div>
);
}
}
render(<App />, document.getElementById('root'));
test.js
import React from "react";
export default function Test() {
return (
<p>test</p>
);
}
Can anyone tell me where I'm going wrong? I've tried to copy the other stackoverflow post and tried test() also. I still get this error:
Error in index.js (18:27) Identifier expected.
Thanks for any help here.
You're trying to use plain Javascript in JSX. You have the right idea but your syntax is wrong. Instead, move your Javascript code (for loop) out to your render() method (above the return())
render() {
let items = []
for (let i = 0; i < 5; i++) {
items.push(<Test key={i} />)
}
return (
<div>
{items}
</div>
);
}
Few things to note here:
Components that are being iterated over, need a unique key property. In this case, we can use the current value of i
Elements can be rendered in JSX by wrapping them in curly braces, shown above. { items }
JSX will accept you any valid JavaScript expressions, Declarative vs Imperative Programming maybe this source can help you. You can create a declarative solution like those shown by the other colleagues (and the best solution), and also you can wrap your imperative solution into a function or method.
const Test = () => {
return (
<p>test</p>
);
}
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
createElements = () => {
const elments = [];
for (var i=0; i < 5; i++) {
elments.push(<Test />)
}
return elements;
}
render() {
return (
<div>
{this.createElements()}
</div>
);
}
}
// Render it
ReactDOM.render(
<App />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
You need a returned value inside the JSX to be able to display anything, here's how you can do that:
const Test = () => {
return (
<p>test</p>
);
}
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div> { Array.from(Array(5)).map(el => <Test />) } </div>
);
}
}
// Render it
ReactDOM.render(
<App />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
You can't use a for loop like this in your return. I would recommend you using a map for this and looping over an array. You can do this by simply creating an array and directly mapping over it :
[...Array(totalSteps)].map(el => el {
return (
<Test />
)
})
You will have to surround this whole block in {}. This will create an array of totalSteps items and return totalSteps <Test />. So if totalSteps is 5, you'll be rendering that component 5 times. This is how your final component should look like :
render() {
return (
<div>
{[...Array(totalSteps)].map(el => el {
return (
<Test />
)
})}
</div>
);
}
For Dynamic Implementation, you can just pass an object to the parameter and display its different values in different components.
We will use map to iterate through the array of objects. Following is the example code in this regard:
return (
<>
{userData.map((data,index)=>{
return <div key={index}>
<h2>{data.first_name} {data.last_name}</h2>
<p>{data.email}</p>
</div>
})}
</>
In my scenerio, the following code helped me to generically generate multiple cards on the same page using a loop (map):
{data.map((data1, id)=> {
return <div key={id} className='c-course-container-card'>
<Courses
courseid = {data1.courseid}
courselink = {data1.courselink}
img = {data1.imgpath}
coursetitle = {data1.coursetitle}
coursedesc = {data1.coursedesc}
/>
</div>
})}
Hope it helps! :)
I have a HTML page, and I am inserting inside as a component a Reactjs.
I am reading the DOM with JavaScript vanilla and I want to insert it on this new react script.
<HTML>
<div id="element">the value I want</div>
<div id="root"></div>
</HTML>
The div id "root" is where the react was inserted
I want to play with the "value" from the DOM, but inside of React
Can I do it? How
Looks like you can add it to componentWillMount before the initial render.
HTML
<div id="element">the value I want</div>
<div id="root"></div>
JSX
class Test extends React.Component {
componentWillMount() {
const { element } = this.props;
this.text = document.getElementById(element).textContent;
}
render() {
return <div>{this.text}</div>;
}
}
ReactDOM.render(
<Test element="element" />,
document.getElementById('root')
);
DEMO
If you pass it as a prop, your component won't rely on the structure of the DOM, making it a little bit more reusable and testable:
const value = document.getElementById('element').value;
ReactDOM.render(
<App value={value}>,
document.getElementById('root')
);
or as Juan Mendes mentioned, pass in the elementId as a prop.
All you need is this
<div ref={(ref) => { this.myDiv = ref; }} />
And then you can get what ever you want from it with.
this.myDiv
import React from 'react';
import ReactDOM from 'react-dom';
class Parent extends React.Component {
let name=this.props.name;
render() {
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);e
Hi All,I'm new to React and i'm stuck in a problem,i wanted to display the name through props but its not working, if i use name=this.props.name inside render() it works fine,But how to get its value outside render,Please help out and Thanks in advance
According to the ES wiki
There is (intentionally) no direct declarative way to define either
prototype data properties (other than methods) class properties, or
instance property
Class properties and prototype data properties need be created outside
the declaration.
Properties specified in a class definition are assigned the same
attributes as if they appeared in an object literal.
a class definition defines prototype methods - defining variables on the prototype is generally not something you do.
To get the value outside of render, you can have a variable in the constructor and then access its value like
class Parent extends React.Component {
constructor(props) {
super(props);
this.name = props.name
}
render() {
return (
<h1>
{this.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
With the Es7 initializers. you can do
class Parent extends React.Component {
name = this.props.name
render() {
return (
<h1>
{this.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
However, since you are assigning a value based on the props, the ideal method is to make use of lifecycle functions and then use it. If you want to update in a state, then the better palce is to have this logic in the componentWillMount and the componentWillReceiveProps fucntion.
However if you only want to update the variable and use it in render, the best place is to have it in the render function itself
class Parent extends React.Component {
state = {
name: ''
}
componentWillMount() {
this.setState({name:this.props.name});
}
componentWillReceiveProps(nextProps) {
this.setState({name: this.props.name});
}
render() {
return (
<h1>
{this.state.name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
or
class Parent extends React.Component {
render() {
let name = this.props.name
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
import React from 'react';
import ReactDOM from 'react-dom';
class Parent extends React.Component {
let name=props.name; // no need to use this.props.name
/* but a better way is to directly use {this.props.name}
inside the <h1> tag if you are not manipulating the data.
*/
render() {
return (
<h1>
{name}
</h1>
);
}
}
ReactDOM.render(
<Parent name="Luffy"/>,
document.getElementById('app')
);
I'm studying ReactNative.Navigator.renderScene props.
'use strict';
import React,{Component} from 'react';
import ReactNative from 'react-native';
const {
TouchableHighlight,
Navigator,
AppRegistry,
Text,
View,
} = ReactNative;
class TestClass extends Component{
render(){
return <Text>test</Text>
}
}
class MyTag extends Component{
render(){
return <Text>test</Text>
}
}
class Main extends Component{
render(){
const routes =[{component:TestClass,index:0},{component:MyTag,index:1}]
return(
<Navigator
initialRoute={routes[0]}
initialRouteStack={routes}
renderScene={(route, navigator) =>
<View><TouchableHighlight onPress={() => {
if (route.index === 0) {
navigator.push(routes[1]);
} else {
navigator.pop();
}
}}><View>{route.component}</View>
</TouchableHighlight></View>
}
/>
)
}
}
AppRegistry.registerComponent('ChoiceComponent', () => Main);
Can component in routes variable be called by using {route.component} in renderScene props in JSX?
TestClass is called correctly if {route.component} is changed into <Test Class />.
You're asking if you can use an object property (route.component) in place of a class name. Absolutely! Remember, these are just identifiers. You use it exactly the same way you used the class name.
So instead of
{route.component}
you want
<route.component />
(But keep reading, we may have to do more.)
Example:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => <route.component text="Hi there" />)}</div>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
The above works, but as far as I can tell from the React documentation, our component identifier name should start with a capital letter:
User-Defined Components Must Be Capitalized
When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
In our case, it's route.component, which is currently handled correctly (because of the .; it wouldn't if it were route_component, for instance), but that appears to be undocumented behavior. (Supporting the . is documented behavior, what appears undocumented is allowing you to start with a lower-case letter when it's not a simple identifier.)
So I think to be officially in line with the docs, we'd want to assign that to a capitalized identifier:
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
Like so:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => {
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
})}</div>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>