Make the Clock component truly reusable and encapsulated? in React JS? - javascript

function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Question:
people, please explain the below code, here how are we moving to the second function like{without kind of any callback function}?

You can achieve this by moving your setInterval up in your component and use it to update its state to make it re-render.
Also, reactDOM.render should only ever be called once.
Working example :
class Clock extends React.Component{
state = { date: new Date() }
componentDidMount(){
setInterval(() => { this.setState({ date: new Date() })}, 1000);
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Related

Is there a way to conditionally render content using onClick in react JS?

Is there a way to achieve conditionally rendered content below but instead of using {renderAuthButton()} in the return statement, I want to achieve running renderAuthButton() with onCLick instead?
class App extends Component {
// ...
render() {
let {isLoggedIn} = this.state;
const renderAuthButton = () => {
if (isLoggedIn) {
return <button>Logout</button>;
} else {
return <button>Login</button>;
}
}
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
{renderAuthButton()}
</div>
);
}
}
I don't really understand your need but to render conditionally, you can do something like that
state = {
show: false,
}
<div className="App">
<button onClick={() => this.setState((prev) => { show: !prev.show })}>Toggle</button>
{this.state.show && <MyComponent />}
</div>
I'm not completely sure what you're trying to do but this is how you would conditionally render content in react:
class App extends React.Component {
constructor(props){
super(props);
this.state = {
show: false
}
this.toggleShow = this.toggleShow.bind(this);
}
toggleShow(){
this.setState({show: ! this.state.show})
}
render(){
return (
<div>
<button onClick={this.toggleShow}>Filter Content</button>
{this.state.show ? (
<p>This content is conditionally shown</p>
) : (
<p>The content is now hidden</p>
)}
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"))
<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>
<div id="root"></div>

React render inside class tag instead id

In my application, I have a requirement to render same data into multiple places via react.
So instead of rendering that via id (via below code), i want to use class tag.
ReactDOM.render(<App />, document.getElementById('app')); // Working
ReactDOM.render(<App />, $('.app')); // Not working.
My html is like below...
<div class="app" id="app"><div>
<div class="app"><div>
<div class="app"><div>
Update: below is my jsx file.
class PList extends React.Component {
static defaultProps = {
results: []
}
constructor(props) {
super(props);
this.state = {
results: this.props.results
};
}
render() {
return (
<ul>
{
this.state.results.map((item, i) => {
return <li>{item.Name}</li>
})
}
</ul>
);
}
}
var PRender = ReactDOM.render(<PList />, $('.app'));
function Professionals(data) {
PRender.setState({
results: data.Results
});
}
$('.app') - this is just an array, and ReactDOM.render requires single element as second parameter.
You can try as following if you need to render multiple App.
function App({index}) {
return `<div>App - ${index}</div>`;
}
document.querySelectorAll('.app').forEach((app, index) => ReactDOM.render(<App index={index + 1} />, app));
<html>
<div id="app">No ID assigned to App</div>
<div class="app"></div>
<div class="app"></div>
<div class="app"></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>
</html>
Here's the answer for your edition.
https://codesandbox.io/s/hopeful-payne-1tloe?fontsize=14
Same as #Alona's answer. I tried to use jQuery -> $('.app') which described on question.
function App({index}) {
return `<div>App - ${index}</div>`;
}
$.each($('.app'), (index, app) => ReactDOM.render(<App index={index + 1} />, app))
<html>
<div class="app" id="app"></div>
<div class="app"></div>
<div class="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<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>
</html>

image onClick failing in React

I have a React component which renders an image. That image has to capture the onClick event, but it doesn't. There is no reason for this behavior. Here is the code:
class MyComponent extends React.Component {
imageClick = () => {
console.log('Click!!!!');
}
render () {
return (
<div>
<img src='/myfolder/myimage.png' onClick={this.imageClick} />
</div>
);
}
}
I can't see why it doesn't shows me back the 'Click!!!!' message in the browsers console when click on the image. It gives me back no error, no warning, no nothing. I'm using Chrome 62.0.3202 running on Linux Mint.
When isolated this code it works, but within boilerplate it does not, which is my case.
What am I missing here?
class MyComponent extends React.Component {
render () {
const imageClick = () => {
console.log('Click');
}
return (
<div>
<img src={require('/myfolder/myimage.png')} onClick={() => imageClick()} />
</div>
);
}
}
I've been playing with create-react-app and noticed that logo had pointer-events css style set to none which disables all the clicks. Not sure if that is your case. Just try to override that style in your img:
<img src='/myfolder/myimage.png' onClick={this.imageClick} style={{"pointer-events": "all"}} />
Well it does work in my case :
class MyComponent extends React.Component {
imageClick = () => {
console.log('Click!!!!');
}
render () {
return (
<div>
<img src='http://www.libpng.org/pub/png/img_png/obj_64x64.png' onClick={this.imageClick} />
</div>
);
}
}
ReactDOM.render(<MyComponent />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
And the same version with a prop (url) passed to the component, as well as as state modification triggered when you click the image, as those two are important in React :
class MyComponent extends React.Component {
constructor(props){
super(props);
this.state = {
clicked : false
}
}
imageClick = () => {
console.log('Click!!!!');
this.setState({
clicked: true
})
}
render () {
return (
<div>
<img src={ this.props.url } onClick={this.imageClick} />
{
this.state.clicked &&
<div>You clicked me!</div>
}
</div>
);
}
}
ReactDOM.render(<MyComponent url="http://www.libpng.org/pub/png/img_png/obj_64x64.png" />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Hope this helps!
Your code looks fine and here is the working sample with image onClick. I have tested on my machine Chrome 16.0 working fine.
<!DOCTYPE html>
<html>
<head>
<title>React Image Click</title>
<meta charset="utf-8">
<script crossorigin src="https://unpkg.com/react#16.0.0/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16.0.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script type="text/jsx">
class MyComponent extends React.Component {
imageClick = () => {
console.log('Click!!!!');
}
render () {
return (
<div>
<img src='/myfolder/myimage.png' onClick={this.imageClick} />
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById("app")
);
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
ImageClick () {console.log('clicked');}
Just define the method as above and call the function like
onClick={this.ImageClick.bind(this)}
Hope it works
I have Found an alternative way to do that ....
I put image inside a button tag, and style that button to show nothing but image.
take a Look at my code :-)
<button style={{background:'none', border:'none'}}>
<img
style={{cursor:'pointer'}}
src={prova}
type="submit"
onclick={() => setTimeout(this.handleBtnClick(touched, errors),1)}
/>
</button>

Render an array of Objects in ReactJs

I am trying to go through object properties (Name for this example) and list them within easy loop in function. I have found some pretty awkward way of doing this but it doesn't seem right.
Here is what i got:
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
const a = props.numbers;
return (
<ul>
{a.map((number) =>
<ListItem value={ItemsToSell[number].Name} />
)}
</ul>
);
}
const numbers = [0,1, 2];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Is there a better way to do this?
I simply need a loop to go through array of objects, list needed properties and create one of many html nodes.
You can simply map over ItemsToSell array
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
return (
<ul>
{ItemsToSell.map((obj, index) =>
<ListItem key={index} value={obj.Name} />
)}
</ul>
);
}
ReactDOM.render(
<NumberList />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Why don't you iterate over ItemsToSell array? You don't have to add yet another one.
Note: Include key property while looping the elements, else you will receive an error.
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
return (
<ul>
{ItemsToSell.map((elem, index) =>
<ListItem value={elem.Name} key={index} />
)}
</ul>
);
}
ReactDOM.render(
<NumberList />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

React: Access element's text

My component is used inside other render() like
return (<MyElem>Some text here</MyElem>)
How can I access the "Some text here" string inside my component's class?
You use the children property, which contains the children of your element (which might be text or an array of children [I think it's always an array when it's not text], see the link for the gory details). E.g.:
const Foo = props => {
console.log(props.children);
return (
<div>{props.children}</div>
);
};
ReactDOM.render(
<Foo>Hi There</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
That uses a stateless functional component (SFC), but it's the same for Component subclasses:
class Foo extends React.Component {
render() {
console.log(this.props.children);
return (
<div>{this.props.children}</div>
);
}
};
ReactDOM.render(
<Foo>Hi There</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Here's an example of the fact that children isn't just for text:
class Foo extends React.Component {
render() {
console.log(this.props.children);
return (
<div>{this.props.children}</div>
);
}
};
ReactDOM.render(
<Foo>
<div>Hi there</div>
<Foo><span>nested Foo > Foo > span</span></Foo>
</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Add a ref to To MyElem:
<MyElem ref="elem">My text here<MyElem>
Then you can refer to your element elsewhere with:
this.refs.elem

Categories