How to use React ContextAPI in static html file - reactjs

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>

Related

I have problem with "when a class component is re-rendered or updated and which methods are called in each case" in React

There is a component sample in React official site which runs a timer. I am wondering why the timer runs in this snippet:
class Clock extends React.Component {
constructor(props) {
super(props);
}
render() {
this.state = {date: new Date()};
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const tick = () => {
root.render(<Clock />);
}
setInterval(tick, 1000)
<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<div id="root"></div>
</body>
</html>
but the timer does not run in this code:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const tick = () => {
root.render(<Clock />);
}
setInterval(tick, 1000)
<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<div id="root"></div>
</body>
</html>
So, when putting this.state = {date: new Date()}; inside constructor the timer does not run, but putting it inside render makes the timer to run.
I have read in React DOCs that:
Mounting
These methods are called in the following order when an instance of a
component is being created and inserted into the DOM:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
Updating
An update can be caused by changes to props or state. These methods
are called in the following order when a component is being
re-rendered:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
So I can conclude that the code inside the constructor runs just once when the component renders or mounts (am I correct?), but does const tick = () => { root.render(<Clock />);} setInterval(tick, 1000) mean that the component is mounting or rendering every second or does it mean that the component is being updated every second? Because if it means that the component is being re-rendered or re-mounted every second, then the constructor must be executed each time, so the second snippet must run the timer too, while it does not.

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

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.

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>

How to pass a json array in react?

First of all I want to clear this I am using cdn for react and using ajax for fetching the details from the json file.
So,I have a json file reactjs.json which looks like...
[
{
"e64fl7exv74vi4e99244cec26f4de1f":[ "image_1.jpg","image_2.jpg"]
}
]
index.html
<!DOCTYPE html>
<html>
<head>
<title>Image Viewer-Static</title>
</head>
<body>
<div id="root"></div>
<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#6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/babel">
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
axios.get('reactjs.json').then(res => {
console.log(res.data);
this.setState({ images: res.data });
});
}
render() {
const { images } = this.state;
return (
<div>
{this.state.images.map((images, index) => (
<PicturesList key={index} apikeys={images.e64fl7exv74vi4e99244cec26f4de1f} />
))}
</div>
);
}
}
class PicturesList extends React.Component {
render() {
return (
<img src={this.props.apikeys} alt={this.props.apikeys}/>
);
}
}
ReactDOM.render(
<FetchDemo/>,
document.getElementById("root")
);
</script>
</body>
</html>
I want to show the image named image_1.jpg,image_2.jpg but this.props.apikeys fetch the value like image_1.jpg,image_2.jpg
images
But I want that it gives two values and show the two image.
I tried a lot to solve this but fails.Any suggestion and help will be welcomed.
Here you are setting the array [ "image_1.jpg","image_2.jpg"] to apiKeys in
<PicturesList key={index} apikeys={images.e64fl7exv74vi4e99244cec26f4de1f} />
So when you try to set the image src here
<img src={this.props.apikeys} alt={this.props.apikeys}/>
what you are setting as this.props.apikeys to src is an array. You have to handle the two images in the array separately to set the source of each image as a String. Try as follows.
{this.props.apikeys.map((image, index) => (
<img src={image} alt={image}/>
))}
since you already have the json file in the file structure you can just import and use it..
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import reactjsJSON from "./reactjs.json";
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: reactjsJSON
};
}
** Edit: **
Your html file
<!DOCTYPE html>
<html>
<head>
<title>Image Viewer-Static</title>
</head>
<body>
<div id="root"></div>
<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#6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/babel">
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
axios.get('/reactjs.json').then(res => {
console.log(res.data);
this.setState({ images: res.data });
});
}
render() {
const { images } = this.state;
return (
<div>
{ this.state.images.map(imageObjs =>
Object.keys(imageObjs).map(key =>
imageObjs[key].map((image, index) => (
<PicturesList key={index} apikeys={image} />
))
)
)}
</div>
);
}
}
class PicturesList extends React.Component {
render() {
console.log(this.props)
return (
<img src={this.props.apikeys} alt={this.props.apikeys}/>
);
}
}
ReactDOM.render(
<FetchDemo/>,
document.getElementById("root")
);
</script>
</body>
</html>
Your JSON, tested for all possibilities, replaced with dummy images
[
{
"e64fl7exv74vi4e99244cec26f4de1f": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
],
"e64fl7exv74vi4e99244cec26f4deop": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
]
},
{
"e64fl7exv74vi4e99244cec26f4de1g": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
]
}
]
serve both the files in same http server and check the output.... since both files are served from same server u can add './' path to fetch and get JSON data...
Looks to me like you are receiving this JSON repose & then setting a JSON object into your state. Try looking at
JSON.parse()
. Your also setting the whole JSON object to your images array. You need select a key.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
I write a demo in codesandbox: https://codesandbox.io/s/oorn5o162q, you can check it out.
I use two real image urls in json, and refine your component code.

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