How to insert a DOM value in a react React component? - javascript

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

Related

weird html rendering issue with react

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>

React: How to do conditional checks from render() method in functional Components?

In my normal React class Components, I have done some checks in the render() method, before returning conditional html rendering. Now, I was using a react functional component, which apparently does not have the render() method... how would I do the conditional checks here? Just Inside normal functions and then return html code from those functions?
e.g Class Component:
render() {
let test;
if (this.state.test ===true) {
test = (
<p>This is a test</p>
)
}
return(
{test}
)
}
in functional components? :
return (
<p >
{checkIcon()} //normal Javascript functions?
</p>
)
As stated by others you can do anything inside a render function, the same things you could do with a class component. You can think of your functional components as the render function of your class ones...
Functional components, by the way, should not contain that much business logic, it'd be better to enhance them with HOCs and function composition.
You might want to have a look at recompose, in which my example takes inspiration from. (change the test attribute and press run code snippet)
// First create a Generic HOC that embedds the branching logic for you.
const branch = (predicate, LeftComponent) => RightComponent => props => (
predicate(props) ? <LeftComponent {...props} /> : <RightComponent {...props} />
);
// Leave your view component the only job of displaying data to the screen. Avoid any control flow.
const Test = () => 'this is a test component';
const Value = ({ value }) => <div>The Value is {value}</div>;
// Create a final component that branches accordingly with the needed check (if props.test is true)
const Component = branch(
props => props.test,
Test
)(Value);
ReactDOM.render(
<Component test={true} value="£100" />,
document.getElementById('container')
);
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="container"></div>
You can think of functional component as a render method of class component where you can do the exact same thing that you do in render except that you will receive props from the arguments instead of this and similarly you won't have state unless your using hooks. So you would pass test as a prop to the functional component
const MyComponent = ({test}) =>{
let value;
if (test ===true) {
test = (
<p>This is a test</p>
)
}
return(
{value}
)
}

Transfer component in props with children method

Its possible to transfer component in props with children method?
I have to components:
let a = (<div>
<button onClick={TContainer.METHOD}>TuCLIK</button>
</div>);
<TContainer data={ restaurantList } component={a}/>
I want to call method in childen but create element in parent. I want to pass this component on props.
If its possible i dont know what writing in TContainer.METHOD to call childen method
You are not passing a component in your props, it's an expression.
A component should be either a class the extends React.Component or a function that returns a jsx markup.
Now when we know that components are just functions, we know that we can pass parameters to them, hence we can pass a function reference as a parameter:
let A = (onClick) => <div><button onClick={onClick}>TuCLIK</button></div>;
<TContainer data={ restaurantList } component={<A onClick={TContainer.METHOD} />}/>
Note that components should be capitalized.
Edit
As a followup to your comment, sorry but i misunderstood your question i guess.
You can't pass a reference of a method from a React component like that.
We can use couple of approaches regarding this scenario, one of them
is to use this.props.children and pass the child component as a
child.
For example - <Parant><Child/></Parent>
We can pass the child component as a prop.
For example - <Parent component={Child} /> or <Parent component={<Child />} />
We can write the parent component as a HOC and wrap the child
with it.
For example - Parent(Child)
In all the above examples you can't pass directly a reference of a function that is declared inside the parent's scope (as a prop to the child).
In order to pass the child a prop within the parent's internal scope you should do it inside the render method.
For example:
render() {
return (
<div>
<this.props.component onClick={this.handleClick}/>
</div>
);
}
This is a snippet that demonstrate one of the examples above:
const Child = ({onClick}) => <div onClick={onClick}>Im a child, Click me!</div>
class Parent extends React.Component {
constructor(props){
super(props);
this.state = {
counter: 0
}
this.addCount = this.addCount.bind(this);
}
addCount(){
this.setState({counter: this.state.counter + 1});
}
render() {
return (
<div>
<div>{`Count = ${this.state.counter}`}</div>
<this.props.component onClick={this.addCount}/>
</div>
);
}
}
const App = () => <Parent component={Child} />;
ReactDOM.render(<App />, document.getElementById('root'));
<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="root"></div>

Specifying variable outside of render in React class

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')
);

How to pass an element between two components in reactJS

I recently have begun learning reactjs and I am having a hard time comprehending state and how it's used. I have built two stateless components (boxOne and boxTwo) and I have a property "Move Me" that I would like to pass between the two components on the click of a button (MoveButton). Below is the code to where I reached to before getting stuck
class MoveButton extends React.Component {
render() {
return (
<button className="thebutton">
Click To Move
</button>
);
}
}
class BoxOne extends React.Component {
render() {
return (
<div className="boxOne-container">
{this.props.name}
</div>
);
}
}
class BoxTwo extends React.Component {
render() {
return (
<div className="boxTwo-container">
</div>
);
}
}
function App() {
return (
<div>
<BoxOne name="Move Me" />
<BoxTwo />
<MoveButton />
</div>
);
}
ReactDOM.render(<App />,document.getElementById('container'));
Okay, so here is a codepen with everything working.
Here is the code for future generation in the event codepen dies before S-O (I think you can run it here as well??).
class Box extends React.Component {
render(){
return (
<div>
{this.props.name ? this.props.name : "nothing"}
</div>
);
}
}
class MoveButton extends React.Component {
render(){
return(
<button onClick={this.props.on_click_handler}>
Click Me
</button>
);
}
}
class App extends React.Component {
constructor(props){
super(props);
this.state = {
first_button: true
};
this.on_click_handler = this.on_click_handler.bind(this);
}
on_click_handler(){
this.setState({
first_button: !this.state["first_button"]
});
}
render() {
return (
<div>
<Box name={this.state["first_button"] ? "Move Me": null} />
<Box name={!this.state["first_button"] ? "Move Me": null} />
<MoveButton on_click_handler={this.on_click_handler} />
</div>
);
}
}
ReactDOM.render(<App />, 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>
So, anyways... here's the explanation.
Basically what you want to do is have the higher level component deal with the state. In this case, we're talking about App. Eventually you'll start to learn where state should go, but generally you want it to be at the highest point that makes sense. Basically, in this case since the App component has the thing (the button) that is changing the state of the two Box we want the state there.
I make the actual function that deals with the click inside the App component, and pass it down to the sub component, MoveButton. I do this because the function is changing state in the App component, so it has to be there. I also had to bind the this in the constructor, which is this line: this.on_click_handler = this.on_click_handler.bind(this);. This just makes sure that this is always referencing the correct thing inside that function.
Then in that handler function I change the components state, which causes a re-render. I use the ternary operator to see which instance of Box I should be passing the "Move me" to. I also use the ternary operator in Box itself to either put the name, or "nothing" but you can change that whatever.
Hope that helps.
P.S: You don't need two different component classes for Box. They're the same thing, so just reuse the same component, but make two instances of it. Which is what I did here.
First off I'd strongly suggest to read the entire react documentation: https://facebook.github.io/react/docs/hello-world.html (or at the very least, to start off the whole quick start section, which covers all the basic you need). It covers pretty much all of react (React has quiet a small scope!).
You need to have some kind of state. Currently your class components (MoveButton, BoxOne and BoxTwo) have access to state but don't use it. Your App component defined as function does not have access to any kind of own state.
Your state needs to be in a common parent component, which you can then pass down to child components as props. The child components may be stateless. In your case that would be the App Component, which you could use a class for instead to make react state available, while the other three components you could rewrite to be stateless functions.
Now I don't understand what exactly you want to happen, I'll just assume you want to move the "Move me" text from one Box to the other on clicking the button. Therefore both boxes have the ability to display text, controlled by the parent. Both boxes could have a react prop called 'name', received by the parent (App). The button itself needs to emit an event (callback), defined in the parent and passed down to the button as prop. I'll call that prop 'handleEvent'.
The implementation could look like such:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
function BoxOne(props) {
return (
<div>BoxOne: {props.name}</div>
);
}
function BoxTwo(props) {
return (
<div>BoxTwo: {props.name}</div>
);
}
function MoveButton(props) {
return (
<button onClick={props.handleEvent}>Click to Move</button>
);
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
boxOneName: 'Move me',
boxTwoName: ''
};
this.handleEvent = this.handleEvent.bind(this);
}
handleEvent() {
this.setState({
boxOneName: this.state.boxTwoName,
boxTwoName: this.state.boxOneName
});
}
render() {
return (
<div>
<BoxOne name={this.state.boxOneName}/>
<BoxTwo name={this.state.boxTwoName}/>
<MoveButton handleEvent={this.handleEvent}/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
Everything used in the example is adressed within the react quick start guide.
Let me know if anything is still unclear :)!

Categories