I have two components one is board component other is square component
when I am passing the props from box to square something strange is happening
Code for Board component is
import React from "react";
import Square from "./Square";
const Board = () => {
return (
<div className="board">
<div className="board-row">
<Square value={1}>
<p>hello</p>
</Square>
<Square value={2} />
<Square value={3} />
</div>
<div className="board-row">
<Square value={4} />
<Square value={5} />
<Square value={6} />
</div>
<div className="board-row">
<Square value={7} />
<Square value={8} />
<Square value={9} />
</div>
</div>
);
};
export default Board;
Code for Square component is
import React from "react";
function Square({ value, children }) {
// the curly braces are just destructring
//the values from props passed
console.log(children);
return (
<button type="button" className="square">
{children}
</button>
);
}
export default Square;
The question is console.log(children) is printing an object on my console whereas {console} is showing normal text on button
why is this happening ??
The thing to remember about JSX is that it is much closer to JavaScript than HTML, despite looking more like the latter. The React Docs include a section which shows how simple tags are equivalent to React.createElement calls, which produce objects describing how to render HTML.
props.children is an object which describes createElement calls happening further up the component tree. This allows it to be passed to further utilities like React.Children or React.cloneElement before finally being passed to the renderer. What you see in the console and what you see in the browser are its states before and after it has finally been rendered.
I assume that you mean that console.log(children) produces something similar to this. And you're not sure why {children} in the return value would produce 'normal' text in your browser window.
The reason for this is that children in the Square component is a Javascript object created by React. Your console doesn't know how to display this any better than showing a textual representation of the properties (as you see in the image).
But when you return {children} in your component function, it is handled by React when rendered to your browser window. React does, in fact, know how to display it 'correctly', hence the button with the text as expected.
Related
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 ä ........ </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
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
As per the title I want an overlay to trigger when an image is clicked on, but I then want it to disappear if anywhere other than 3 buttons on the overlay are clicked.
Unfortunately using getElementbyID won't work as the items repeat on a masonry layout.
<Masonry
breakpointCols={breakpointColumnsObj}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column">
{this.state.data.map((data) => (
<div>
<div className="tilebutton" key="" style={{width:'100%',position:'relative'}} href={data.URL} >
<div className="tileoverlay" id="overlay" onClick={overlayoff} onclickout key={data.URL} style={{display:'none',width:'100%',zindex:'2',position:'absolute'}}>
<a className="button1" href={data.URL} onClick>{data.Name}</a>
<a className="button2" href={data.CompURL}>{data.Company}</a>
<a className="button3" href={'instagram.com/'+data.insta}>{data.Company}<img src="\img\Icons\instagram.svg" className='instalogo'/></a>
</div>
<img src={data.img} onClick={overlayon} style={{width:'100%'}}/>
</div>
</div>
))}
</Masonry>
)
function overlayon() {
document.getElementById("overlay").style.display = "block";
}
function overlayoff() {
document.getElementById("overlay").style.display = "none";
}
Unfortunately using the id "overlay" means if I click any version of the masonry it will trigger the overlay on the first image. Is there some way to:
a) identify the element clicked so it will be the one with the toggling overlay
b) have an "onclickout" I could apply to the overlay's buttons
this is about 5 days into my first ever web build so frankly I haven't got a clue what I am doing - any help is appreciated.
Thanks in advance.
The idioms used in React discourages you to manipulate the DOM directly, unless you are doing something special, such as animation. And thus I don't recommend "identifying the element clicked".
With that said, you can manipulate the data, and trigger a redraw accordingly, by invoking some setSate function (in the example below, I've defined a setShouldShowOverlay, that, when invoked, will result in a redraw).
What I recommend is for you to pull out the code inside this.state.data.map() into its own component, like so:
import React, { useState } from 'react';
function Data({ data }) {
const [ shouldShowOverlay, setShouldShowOverlay ] = useState(false);
return (
<div>
<div className="tilebutton" key="" style={{width:'100%',position:'relative'}} href={data.URL} >
<div className="tileoverlay" id="overlay" onClick={() => { setShouldShowOverlay(false); }} onclickout key={data.URL} style={{display:'none',width:'100%',zindex:'2',position:'absolute'}}>
<a className="button1" href={data.URL} onClick>{data.Name}</a>
<a className="button2" href={data.CompURL}>{data.Company}</a>
<a className="button3" href={'instagram.com/'+data.insta}>{data.Company}<img src="\img\Icons\instagram.svg" className='instalogo'/></a>
</div>
<img src={data.img} onClick={() => {
setShouldShowOverlay(true);
}} style={{width:'100%'}}/>
</div>
</div>
);
}
Then finally, update your Masonry code like so:
<Masonry
breakpointCols={breakpointColumnsObj}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column">
{this.state.data.map((data) => (
<Data data={data} />
))}
</Masonry>
. .
I am currently using React VR for a school project, but incorporating vanilla javascript into the index.html to create a static HTML UI. In this case I am using an HTML5 form to post data to my back end, yet still, I would like to optimistically render the data using a React component rather than have to retrieve the data from the server.
My data is created in the HTML element, and it needs to make its way into a React Component.
I don't think refs will work, as the research I have done shows that they are for accessing data which is being generated by a React component, and in my case, I am looking for the data to flow from the HTML to the React Component.
~ JAVASCRIPT & HTML ~
//Accepts the Input
<form id='idea-form'>
<input type="text" id="hiddenInput" maxlength=95 autocomplete=off>
</form>
// Initialize the React VR application.
ReactVR.init(
'../index.vr.bundle?platform=vr&dev=true',
document.body
);
I've included my component here, minus imports and exports.
The component maps an array of strings, converts them to JSX, then renders components with the array elements as the text props for the component.
In my case,
//========== IdeaContainer Component ==========
class IdeaContainer extends Component {
//---------- Other Methods ----------
mapIdeasContentToJSX(ideasObjArr) {
newIdeas = [...ideasObjArr]enter code here
ideasJSX = newIdeas.map((idea) => {return (<IdeaText
text={idea.content}
y={Math.random() * 30}
z={Math.random() * -80}
/>)})
return ideasJSX
}
//---------- Lifecycle Methods ----------
componentDidMount(){
this.props.preLoadIdeas()
}
render(){
return(
<View>
{this.mapIdeasContentToJSX(this.props.ideaList)}
</View>
)
}
}
This is the code which lives in the index.html, which exists outside the scope of my React components, meaning I cannot pass it as props or set it to state, as far as I know.
The element with id of 'container' is where the data is being entered, which then needs to make its way to the React Component
<div>
<div id='logoDIV'class="relative" >
<img id='logoIMG' src='./logo.png' draggable="false">
</div>
</div>
<div id="container" style='position: fixed; z-index: 2; bottom: 1%; right: 22%;'>
<div id="input"></div>
<form id='idea-form'>
<input type="text" id="hiddenInput" maxlength=95 autocomplete=off>
</form>
</div>
<canvas id="cloudCover"></canvas>
<!-- When you're ready to deploy your app, update this line to point to your compiled client.bundle.js -->
<script src="./client.bundle?platform=vr"></script>
<script src="./input.js"></script>
<script src='./clouds.js'></script>
<script>
ReactVR.init(
// When you're ready to deploy your app, update this line to point to
// your compiled index.bundle.js
'../index.vr.bundle?platform=vr&dev=true',
document.body
);
</script>
<script>
let x = document.body.querySelector('body > div:nth-child(8) > div > a:nth-child(2)')
x.style.bottom = '100px'
</script>
You are looking for refs.
<input
type="text"
id="hiddenInput"
maxlength=95
autocomplete=off
ref={(input) => { this.textInput = input; }} />
Then you can access the input value like this:
this.textInput.value
https://reactjs.org/docs/refs-and-the-dom.html
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>`);
}