How to implement a React equivalent of Vue's IS attribute? - reactjs

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.

Related

Get Root DOM element from a child component

I have a loop that reads multiple elements from the document and I render it with ReactDOM.render, and a component very low in the component tree, creates a custom event, to that event I would like to pass the element that was rendered in the DOM (i.e. Root Element), I have to go passing from the top the element through Props, or React provides some API that can tell me which Root element we are?
Rather, in the child component, I would like to make: rootElement.dispatchEvent(myCustomEvent);
What options do I have to do this?
The root node looks to be given a property that starts with __reactContainer, so you can search through parent elements until you find an element with such a property.
const Child = () => <div><span onClick={(e) => {
let element = e.target;
while (element) {
element = element.parentElement;
if (Object.keys(element).some(key => key.includes('reactContainer'))) {
console.log('Found', element);
break;
}
}
}}>click</span></div>;
const App = () => {
return <section><Child /></section>
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div class='react'></div>
That's almost certainly not part of the deliberate outward-facing design, though. A better way would be to use useContext to save the root element at the top component via a ref, and to consume it in the descendant component.
const Child = () => {
const { ref } = React.useContext(Context);
return (
<div>
<span
onClick={() => { console.log(ref.current.parentElement); }}
>click</span>
</div>
);
};
const Context = React.createContext();
const App = () => {
const ref = React.useRef();
return (
<Context.Provider value={{ref}}>
<section ref={ref}><Child /></section>
</Context.Provider>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div class='react'></div>

How to use React ContextAPI in static html file

I have static html file and used umd script like:
<script src="https://unpkg.com/react#16.8/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16.8/umd/react-dom.production.min.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js" crossorigin></script>
I can use <MyContext.Provider> and <MyContext.Consumer>. But unable to use
static contextType = MyContext;
The output to console.log(this.context) is getting an empty object
I am running this example from https://medium.com/#muddassirm/react-context-api-made-simple-a778ec819fa7 . This does seem to work !
Code running in Plunker https://plnkr.co/edit/A4YCEJR3GvqVgs6X?preview
const Context = React.createContext();
const ContextApp = () => {
return (
<Context.Provider value={['THE', 'QUICK', 'BROWN', 'FOX', 'JUMPS', 'OVER', 'THE', 'LAZY', 'DOG']}>
<CustomComponent/>
</Context.Provider>
)
}
class CustomComponent extends React.Component {
render(){
let context = this.context
return(<div>{context.map((item) => <li>{item}</li>)}</div>)
}
}
CustomComponent.contextType = Context
// Render it
ReactDOM.render(
<ContextApp />,
document.getElementById("react")
);
<div id="react"></div>
<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>

Does react element itself has inner text, inner html?

Learning react, i see element examples like this,
const element = <Welcome name="Sara" />;
Does it support ?
const element = <Welcome name="Sara">good day </Welcome>;
If so, how to get "good day" while "name" belongs to props ?
Thanks !
The content of the element is exposed through the children prop.
const Welcome = (props) => {
return <div>
<p>Hello {props.name}!</p>
{props.children}
</div>
};
ReactDOM.render(<Welcome name="Sara">good day </Welcome>, document.body);
<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>
React has children prop out of the box, which accepts nested content inside Component
function Welcome (props) {
console.log('props.name', props.name)
console.log('props.children', props.children)
return <h1>{props.name} {props.children}</h1>
}
function App () {
return (
<div>
<Welcome name="Sara">good day </Welcome>
<Welcome name="Sara" />
</div>
);
}
ReactDOM.render(<App />, document.body)
<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>

Take a string but need react component

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.

How to add multiple React components to HTML

I wonder if we can add multiple react components into HTML without having the related files usually downloaded with npm, or added to a normal HTML but we add a certain component for a chat app as my attempt here, here is a long example:
<html lang="en">
<head>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<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>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class App extends React.Component{
state={
messages:[
{ }
],
userId:''
}
addMessage=(message)=>{
message.num = Math.random();
message.id=this.state.messages.id;
let messages = [...this.state.messages, message];
this.setState({
messages })
}
addId=(userId)=>{
this.setState({
userId
})
}
render() {
return (
<div className="appContainer">
<User userId={this.addId} />
<TopSection Users={this.state.userId}/>
<Messages userId = {this.state.userId} messages={this.state.messages}/>
<AddMessage addMessage={this.addMessage} />
</div>
);
}
}
}
const Messages = ({messages, userId}) =>{
const messageList= (messages.length)? (messages.slice(1).map(message=>{
return(
<div className="message" key={message.num}>
<span key={userId.num}>{message.content?(userId):(null)}</span>
<p>{message.content}</p>
</div>
)
})) : (null);
return(
<div className="textContainer">
{messageList}
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'));
</script>
</body>
</html>
please let me know if there is away to get this to work.
You mean add components to different dom nodes ?
import {render} from 'reactDOM'
import React from 'react'
import AppOne from './appOne'
import AppTwo from './appTwo'
render(<AppOne />, document.getElementById('appOne'));
render(<AppTwo />, document.getElementById('appTwo'));
React v16 has portals as well for adding componnets to differnt parts of the dom tree

Resources