I have some object like:
'key': { a: 'aa', b:'bb', c: <Component/> }
It object returned as property in some object:
{item.a}
{item.b}
{item.c}
item.c - is a string, but im need take real component in render. Very thanks for any answer!!!
You would convert your values to arrow functions.
Working example :
const data = {
a: () => 'aa',
b: () => 'bb',
c: () => <Component />
}
const App = props =>
<div>
{data.a()}
{data.b()}
{data.c()}
</div>
const Component = props => <p>Comp</p>
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
<div id='root'>
Simply storing your component in a variable will also* work :
const Component = props => <p>Comp</p>
const data = {
a: 'aa',
b: 'bb',
c: <Component />
}
const App = props =>
<div>
{data.a}
{data.b}
{data.c}
</div>
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
<div id='root'>
It should work without any magic, Component here is a function and calling item.c should give you the reference to the function. Double check your code, if it doesn't work then you need to provide more details like how you are calling it.
Related
I have a component, something like,
const ComponentA = ({ heading })=> {
return (<h1>{ heading }</h>);
};
Is there any difference in rendering this component using below two options,
Option 1
const ComponentB = ()=> {
return ComponentA({ heading: 'Heading test' });
};
Option 2
const ComponentB = ()=> {
return <ComponentA heading='Heading test' />;
};
Yes. There is a very important difference. In option 1, ComponentA is not actually a component as far as React is concerned. In option 2 it is.
The best way to illustrate the difference is to put state or another hook inside of ComponentA. Option 1 will not work as expected. (Note: if it does happen to work as expected, you still shouldn't trust it. This is where bugs can sneak in because they don't cause issues until later).
Here is an example where using hooks appears to work, but breaks after you get the counter past 5. This is because React is treating the hooks inside ComponentA as if they belong to Example. Notice how the JSX version works as expected even after it disappears.
const {useState, useEffect} = React;
const ComponentA = ({ id, heading })=> {
React.useEffect(() => {
console.log(id, 'mounted');
}, []);
return (
<h1>
{ heading }
</h1>
);
};
const Example = () => {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Re-render me</button> {count}
{count < 5 ? ComponentA({ heading: 'Heading test1', id: 1 }) : null}
{count < 3 ? <ComponentA heading='Heading test2' id={2} /> : null}
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The reason is JSX (< /> syntax) is actually just a syntax for calling React.createElement. If this is not called, the function component does not get it's own lifecycle, etc. You've bypassed the way React tracks components.
I want to be able to implement:
<div is='a' href='https://stackoverflow.com'>go to Stack Overflow</div>
To render into:
<a href='https://stackoverflow.com'>go to Stack Overflow</a>
What would be the most sensible approach to implement it?
There are a number of ways to do that, but here's one of them:
const CustomComponent = (props) => {
const {is, children, ...rest} = props
return React.createElement(is, {...rest}, children)
}
const App = () => {
return (
<CustomComponent
is={'a'}
href={'https://stackoverflow.com'}
>
go to Stack Overflow
</CustomComponent>
)
}
ReactDOM.render(
<App /> ,
document.getElementById('root')
);
<script src="https://unpkg.com/react#17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
More on React.createElement() here.
afraid that question is simple stupid but im stuck(
I have a Box component with some nested ones:
<Box.Content anyProp="prop">
<Box.Text...
<Box.Links
How I can pass ALL the props form Box.Content to ALL child containers (Box.Text, Box.Links, anything else)?
Trying with no luck:
BoxComponent.Content = (...props) => (
<BoxContent {...props}>{props.children}</BoxContent>
);
Then trying to catch any prop from Parent inside child container - no props listed(
You can use React.cloneElement to dynamically set a parent's props on its children.
Run the following code snippet. prop1 and prop2 on the Parent component are passed to the Child1 and Child2 components.
const Child1 = (props) => <p>Child 1: {JSON.stringify(props)}</p>;
const Child2 = (props) => <p>Child 2: {JSON.stringify(props)}</p>;
const Parent = ({ children, ...props }) => {
children = children.map(v => React.cloneElement(v, props));
return <div id="parent">{children}</div>;
};
const App = () => (
<Parent prop1="foo" prop2="bar">
<Child1 />
<Child2 />
</Parent>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<div id="root"></div>
We know that the useState hook is used for managing state within functional components in ReactJs.
So, for learning purposes I was implementing the example of the useState hook (snippet is given below) wherein I have taken an array with some initial value and I need to update the array and display the whole updated array in the browser whenever I clicked on the button. I tried with the below snippet but didn't get the expected result.
Problem: When I click the button for first time it will add the new element in the array but after clicking the button for two or more times it only overrides the last element.
Expected Result: New elements should be added in the array rather than overriding the last element in the array.
I definitely missing any logic or any important concept of useState hook here in this example. Please help me to understand more on react Hooks.
const {useState} = React;
const Example = () => {
const array = [1,2,3] ;
const [newArray,setNewArray] = useState(array);
const [newElement,setElement]= useState(array[array.length-1]);
const handleBoth = () => {
setElement(prev => prev + 1);
setNewArray([...array,newElement]);
}
const mapping = newArray.map(element => <li> No. {element}</li>)
return (
<div>
<ul>
{mapping}
</ul>
<button onClick={handleBoth}>Add</button>
</div>
);
};
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Use the state newArray not the array for the map implementation. array will reinitialize to [1,2,3] on every render. In fact, you should just move the array constant outside of the component
const {useState} = React;
const array = [1,2,3];
const Example = () => {
const [newArray,setNewArray] = useState(array);
const [newElement,setElement]= useState(array[array.length-1]+1);
const handleBoth = () => {
setElement(prev => prev + 1);
setNewArray([...newArray,newElement]);
}
const mapping = newArray.map(element => <li> No. {element}</li>)
return (
<div>
<ul>
{mapping}
</ul>
<button onClick={handleBoth}>Add</button>
</div>
);
};
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
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.