i want to add paragraph element to my div element on first mount .But on browser ,i see [object Object]. Also,i want to know why i am getting [object Object] on my browser instead of text 'hi' . what changes to be made for 'hi' text instead of [object Object].
import './App.css';
import {useEffect,useState} from 'react'
function App() {
let h=(<p>hi</p>);
useEffect(()=>{
document.getElementById('i').append(h)
},[])
return (
<div id='i' className="App">
</div>
);
}
export default App;
Never use native DOM methods in React unless there's no other option.
Here, you should interpolate the <p> into the returned JSX. Use a boolean state to indicate whether the initial mount has completed.
const { useEffect, useState} = React;
function App() {
const [mounted, setMounted] = useState(false);
useEffect(()=>{
setMounted(true);
},[])
return (
<div id='i' className="App">
{
mounted && <p>hi</p>
}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<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 class='react'></div>
you are getting [object][object] because you are passing object in h.
You can change the code as below to get your desired output,
let h='<p>hi</p>)';
document.getElementById("i").innerHTML += h
Full code below,
//import './App.css';
import React, {useEffect,useState} from 'react'
function App() {
let h='<p>hi</p>)';
useEffect(()=>{
document.getElementById("i").innerHTML += h
},[])
return (
<div id='i' className="App">
</div>
);
}
export default App;
Related
so i am trying to make a program where i can make or create new elements in react js on a click i tried few things but it gives me few errors
import React from 'react'
import { ReactDOM } from 'react'
export default class Create extends React.Component{
render(){
ReactDOM.render(<h1>Hello</h1>,document.getElementById('box'))
return(
<>
<div id='box'></div>
</>
)
}
}
this is what i tried to do where i tried to add a new HEADING element in box element but it gives me a few error
i am new to react so i am sorry for some rookie mistakes
There are tons of way of achieving this behaviour.
One way is to keep track of an Integer, for which you will render an Element (header). Pressing a button will then increase the number, so a new one is rendered.
The same idea can be achieved using arrays, objects etc...
Example using an simple Integer:
const { useState } = React;
const Heading = (props) => {
return <h3>{'Header: #' + (props.id + 1)}</h3>;
}
const Example = () => {
const [num, setNum] = useState(1);
const bumpNum = () => setNum(num + 1);
return (
<div>
<h1 onClick={bumpNum}>{'Press me to bump!'}</h1>
{Array(num).fill().map((_, i) => <Heading id={i} />)}
</div>
)
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
im having an issue getting react portals working. I dont understand why I am receiving error message portal id is not DOM element that is clearly a valid DOM element.
I have a sandbox here
Code in its entirety presented here. The console.log reports correctly that the element is a DOM element but React is throwing an error.
import "./styles.css";
import { createPortal } from "react-dom";
import { useEffect, useState } from "react";
export default function App() {
const [portalDiv, setPortalDiv] = useState(undefined);
useEffect(() => {
let pd = document.getElementById("portalDiv");
console.log(pd);
setPortalDiv(pd);
}, []);
return (
<>
<div id="portalDiv">portal container</div>
<div className="app">
{/* {console.log("render portaldiv", portalDiv)} */}
{
(portalDiv &&
createPortal(
<>
<h1>Inside portal</h1>
</>
),
portalDiv)
}
<h1>Outside portal</h1>
</div>
</>
);
}
Any advice appreciated. Thanks.
This usecase is not recommended as stated in my comment, but here is a reproducible example.
If you intend to inject a React Node into VDOM, you should use React API for that, so you won't get a race condition while querying the DOM via DOM API.
import "./styles.css";
import { createPortal } from "react-dom";
import { useRef } from "react";
export default function App() {
const containerRef = useRef();
return (
<>
<div ref={containerRef}>portal container</div>
<div id="app">
{containerRef.current &&
createPortal(<h1>Example Element</h1>, containerRef.current)}
<h1>Outside portal</h1>
</div>
</>
);
}
im creating a restuarant pos and after passing the props into a seperate component which i use to map data from the api to the html cards, i continuously encounter this error. im using the axios api and it works fine as it displays all the data on the console.log. the initial error i had was o do with the axios api which i believe i fixed but this map function error does not change even when i use other api methods such as fetch.
import styles from "../styles/foodlist.module.css"
import Foodcard from "../components/foodcard"
const Foodlist = ({foodlist}) =>{
return(
<div className={styles.container}>
<h1 className={styles.title}>Popular food</h1>
<div className={styles.wrapper}>
{foodlist.map(food => {
return(
<Foodlist key={food._id} food = {food}/>
)
})}
</div>
</div>
)
}
export default Foodlist
the above code is what produces the error: "TypeError: Cannot read property 'map' of undefined".
the code below is where i defined the prop foodlist
import Head from 'next/head'
import Image from 'next/image'
import Foodlist from '../components/foodlist'
import Welcome from '../components/Welcome'
import styles from '../styles/Home.module.css'
import axios from "axios"
export default function Home({foodlist}) {
console.log('foodlist', foodlist)
// console.log(axios)
return (
<div className={styles.container}>
<Head>
<title>Emilia Plate</title>
<meta name="description" content="Emilia plate, order and pay for any meal offered on our menu" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Welcome/>
<Foodlist foodlist = {foodlist}/>
</div>
)
}
export const getServerSideProps = async () => {
const res = await axios.get("http://localhost:3000/api/products");
// const data = await res.json();
return{
props:{
foodlist: res.data,
}
}
}
when i place the ? in the map function it displays popular foods (the title) several times instead of placing the data that it should map
thanks for taking the time to look at this.
I am struggling to find out how to make this work specifically in react.
I have used contentEditable to get the div element to be editable and then i have used Refs to make the div reference its innerHTML. But the information does not seem to be put into the state of body.
The ultimate aim is to have it saved in a database, and then loaded to replace the div.
code:
import React, {useState, useRef} from "react";
import "./styles.css";
export default function App() {
let myRef= useRef()
const [body, setBody] = useState("");
let click = () => {
setBody(myRef.innerHTML)
}
return (
<div className="App">
<h1 ref={myRef}>Hello CodeSandbox</h1>
<div></div>
<h1 contentEditable={true}> rewrite me!</h1>
<button onClick={click}> CLICK!</button>
<h1>{body}</h1>
</div>
);
}
sandbox
https://codesandbox.io/s/wispy-glitter-nfym4?file=/src/App.js
Access the innerHTML using myRef.current.innerHTML.
From the docs
When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref.
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
function App() {
let myRef = React.useRef();
const [body, setBody] = React.useState("");
let click = () => {
setBody(myRef.current.innerHTML);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div></div>
{/* I think you misassigned your `myRef`, shouldn't it be on this h1? */}
{/* suppressContentEditableWarning=true, to suppress warning */}
<h1 ref={myRef} contentEditable={true} suppressContentEditableWarning={true}> rewrite me!</h1>
<button onClick={click}> CLICK!</button>
<h1>{body}</h1>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
I have a component called Button.js that has a button that when clicked i simply would like to know if i am accessing the a div in another component called Timer.js. In vanilla javascript i would simply use document.getElementById() to capture the DOM node. How is this done in React?
I came across callback-refs in the docs but it isn't working. If using a ref isn't the React way of accessing DOM elements please refer me to the best way to do this. thanks in advance.
Button.js
function Button() {
const getHtml = () => {
const node = test.current;
console.log(node);
}
return (
<button onClick={getHtml}>GetHtml</button>
)
}
Timer.js
function Timer() {
const test = useRef(null);
return (
<div ref={test}>... </div>
<Button />
}
I would not use a reference to check if a component is rendered inside of another one.
You could get what you're looking for with createContext and useContext.
(It could work like you tried it. If you'd pass the ref to the button as a prop.)
With the context: You create a TimerContext.Provider in your Timer component and in your button you can check with useContext(TimerContext) if the expected key is in the object. If it's not there then the button is not inside of your Timer.
Please have a look at the snippet below or in the following Codesandbox.
//import React, { useContext, createContext } from "react";
//import "./styles.css";
const { useContext, createContext } = React;
const ContainerContext = createContext({
isInContainer: null
});
const Container = () => {
return (
<ContainerContext.Provider value={{ isInContainer: true }}>
<p>
In container:
<Button />
</p>
</ContainerContext.Provider>
);
};
const Button = () => {
const { isInContainer } = useContext(ContainerContext);
console.log(isInContainer);
const isInside = () => {
alert(isInContainer ? "clicked inside" : "not in container");
};
return <button onClick={isInside}>Click me</button>;
};
function App() {
return (
<div className="App">
<Container />
<Button />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<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="root"></div>
Update 15.04.2020
The question was not clear to me at first but now I understand the use-case. The idea is to have an Editor component where you're writing markup that can be used to generate a copied snippet view and/or a html markup output.
For this the best is to use a reference to the Editor component and pass it as prop to the preview/output component - it would be also possible with a context but passing it is easier.
Like in the following Sandbox.