REACTJS JSX re render - reactjs

I want to re-render html in App.js what is triggered by click event.
In first load JSX component <WaypointList waypoint_is_done={false} App={this}/> is rendered.
But when i click button then it wont render JSX component <WaypointList waypoint_is_done={true} App={this}/> again.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
content: this.index()//LETS LOAD CONTENT
};
this.index = this.index.bind(this);
this.toggleDoneList = this.toggleDoneList.bind(this);
};
index() {
return <WaypointList waypoint_is_done={false} App={this}/>;
};
//SET NEW RENDERER ONCLICK
toggleDoneList(){
console.log('click');
this.setState({
content: <WaypointList waypoint_is_done={true} App={this}/>
//content: <div>see</div>
});
};
render() {
console.log(this.state.content);
return this.state.content;
};
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);
First time it fire WaypointList class, but when i click button "object-done-listing" then not
It calls the App.toggleDoneList and App.render is also fired and it get correct JSX component but does not fire WaypointList class again
class WaypointList extends React.Component {
constructor(props) {
super(props);
this.App = props.App;
this.state = {
content: this.index(props)
};
this.index = this.index.bind(this);
};
index(props) {
let rows = logistic_route_sheet_waypoint_rows;
if (rows.length > 0) {
return (
<div className="map-listing">
<div className="object-done-listing noselect btn btn-success"
onClick={() => this.App.toggleDoneList()}>
<i className="fa fa-list" aria-hidden="true"></i>
</div>
</div>
);
}
return (null);
};
render() {
return this.state.content;
};
}
It works if i set
this.setState({
content: <div>see</div>
});
but not with
this.setState({
content: <WaypointList waypoint_is_done={true} App={this}/>
});
What is the problem ?

I found a solution to re-renderer the class
i made "CustomEvent" "reRenderer" and i call re_renderer function outside of react.

Related

Why does my "Audio-Button" don`t play a sound (onClick)

I am struggeling on finding out why my button dont play a sound when I click on it. The console.log() test works fine, but the -part dont. I also tried some npm-packets to solve the problem, but it seems like my code has a general problem. Whats wrong with it? Can someone help me?
The main.js :
import Button from './button';
class Drumpad extends Component {
constructor(props) {
super(props);
this.state = {
Q:
{
id: 'Q',
name: 'Q',
src: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3'
},
}
}
render() {
return (
<div style={test}>
<div id='row1'>
<Button cfg={this.state.Q}/>
</div>
</div>
)
}
}
And the button.js:
class Button extends Component {
constructor(props) {
super(props);
this.state = {
}
}
handleClick = () => {
console.log(this.props.cfg.src);
return (
<audio ref='audioClick' src={this.props.cfg.src} type='audio/mp3' autoPlay>
);
};
render() {
return (
<div>
<button style={buttonStyle} onClick={this.handleClick}>
<h1>{this.props.cfg.name}</h1>
</button>
</div>
)
}
}
The handleClick method in button.js returns an <audio> element, which is redundant, since you would like to play the sound onClick.
Instead I used a Audio constructor to create an instance of the audio clip, using the url provided as props, which I set to state.
Then I use a callback to invoke the play() method on it.
handleClick = () => {
const audio = new Audio(this.props.cfg.src);
this.setState({ audio }, () => {
this.state.audio.play();
});
};
So your button.js becomes something like this:
import React, { Component } from "react";
const buttonStyle = {};
export default class Button extends Component {
constructor(props) {
super(props);
this.state = {
audio: false
};
}
handleClick = () => {
console.log(this.props.cfg.src);
const audio = new Audio(this.props.cfg.src);
this.setState({ audio }, () => {
this.state.audio.play();
});
};
render() {
return (
<div>
<button style={buttonStyle} onClick={this.handleClick}>
<h1>{this.props.cfg.name}</h1>
</button>
</div>
);
}
}
Your main.js remains as is.
Here is a working codesandbox.

How to use onload in react?

To run the imagesrore function onload I have to call <img src="image_7.jpg" className="hide" alt="image_7.jpg"/> image but actually there is no use of this line and if I remove this onload doesn't work and function is not called. So how can I call the imagestore() onload in react.
class PicturesList extends React.Component {
constructor(props) {
super(props);
this.state = {
imagesarray: []
};
this.imagestore = this.imagestore.bind(this);
}
render() {
return (
<div>
<div onLoad= {() => this.imagestore()}>
<img src="image_7.jpg" className="hide" alt="image_7.jpg"/>
// To run the imagesrore function onload I have to call this image but actually there is no use of this line and if I remove this onload doesn't work and function is not called
</div>
<Gallery url={this.state.imagesarray}/>
</div>
);
}
imagestore()
{
const imgUrls=this.props.apikeys;
const objarr = Object.values(imgUrls);
this.setState({
imagesarray: objarr
});
}
}
what I want
class PicturesList extends React.Component {
constructor(props) {
super(props);
this.state = {
imagesarray: []
};
this.imagestore = this.imagestore.bind(this);
}
render() {
return (
<div>
<div onLoad= {() => this.imagestore()}>
// but when I did this imagestore() function not called
</div>
<Gallery url={this.state.imagesarray}/>
</div>
);
}
imagestore()
{
const imgUrls=this.props.apikeys;
const objarr = Object.values(imgUrls);
this.setState({
imagesarray: objarr
});
}
}
Instead of rendering the image which you dont want, you could simply load it in componentDidMount like
class PicturesList extends React.Component {
constructor(props) {
super(props);
this.state = {
imagesarray: []
};
this.imagestore = this.imagestore.bind(this);
}
componentDidMount() {
const img = new Image();
img.onload =() => {
// image has been loaded
this.imagestore()
};
img.src = 'image_7.jpg';
}
render() {
return (
<div>
</div>
<Gallery url={this.state.imagesarray}/>
</div>
);
}
imagestore() {
const imgUrls=this.props.apikeys;
const objarr = Object.values(imgUrls);
this.setState({
imagesarray: objarr
});
}
}
The above solution is just to call imageStore once an image is loaded. However if what you intend is to call imageStore when the component has fully loaded,just trigger this.imageStore() in componentDidMount
class PicturesList extends React.Component {
constructor(props) {
super(props);
this.state = {
imagesarray: []
};
this.imagestore = this.imagestore.bind(this);
}
componentDidMount() {
this.imagestore()
}
render() {
return (
<div>
</div>
<Gallery url={this.state.imagesarray}/>
</div>
);
}
imagestore() {
const imgUrls=this.props.apikeys;
const objarr = Object.values(imgUrls);
this.setState({
imagesarray: objarr
});
}
}
Use useEffect() in React. You would use it like this:
useEffect(()=>{
**INSERT CODE YOU WANT RUN ON LOAD HERE **
}, [])
Remember to import useEffect as well with
import React, { useEffect } from 'react'
Your onLoad function should be used at the <img> tag, not the <div/>.

function passed as React prop is not appearing in called child

I have a React component render method defined as below, which includes passing a prop called onExchangeSelect into the ExchangeList component.
render() {
return (
<div className="ExchangeContainer list-group">
<ExchangeList
exchanges={this.state.exchanges} selected={this.state.selectedExchange}
onExchangeSelect={selectedExchange => this.setState({selectedExchange})}
/>
<ExchangeDetail exchange={this.state.selectedExchange} />
</div>
);
}
Then, in the ExchangeList constructor, when I console.log this.props, there is not a prop called onExchangeSelect which I can call and th.
The intent is to pass a callback function from the top level component to a child component, to be called by the child so as to affect the state of the parent component. The entire top-level class is below:
class ExchangeContainer extends Component {
constructor(props) {
super(props);
this.state = {
exchanges:[
{
name:"binance",
url:"https://bittrex.com"
},
{
name:"bittrex",
url:"https://bittrex.com"
}
],
selectedExchange:"binance"
};
}
render() {
return (
<div className="ExchangeContainer list-group">
<ExchangeList
exchanges={this.state.exchanges} selected={this.state.selectedExchange}
onExchangeSelect={selectedExchange => this.setState({selectedExchange})}
/>
<ExchangeDetail exchange={this.state.selectedExchange} />
</div>
);
}
}
Why is the function not available as a prop in the child component? (below):
class ExchangeList extends Component {
constructor(props) {
super(props);
this.state = {
};
console.log('This props ' + JSON.stringify(this.props))
}
render() {
console.log("EL: " + JSON.stringify(this.props))
const ExItemList = this.props.exchanges.map((exchange) => {
return <ExchangeListItem key={exchange.name} exchange={exchange}
onExchangeSelect={this.props.onExchangeSelect}/>
});
return (
<ul className="col-md-4 list-group bg-light" >
{ExItemList}
</ul>
);
}
}
i would inspect them in dev tools instead of console.log..place break point and check in chrome dev tool.. onExchangeSelect should be available as part of props in child component..
the offical docs says you should bind the method to a property inside the constructor function. you can play around on my codesandbox for the code below
constructor(props) {
super(props);
this.state = {
exchanges: [
{
name: "binance",
url: "https://bittrex.com"
},
{
name: "bittrex",
url: "https://bittrex.com"
}
],
selectedExchange: "binance"
};
// bind "this" to handleOnExchange method
this.handleOnExchange = this.handleOnExchange.bind(this);
}
// method to be bound
handleOnExchange (data) {
this.setState({selectedExchange: data})
}
render() {
const ExchangeList = props => <div />;
const ExchangeDetail = props => <div />;
return (
<div className="ExchangeContainer list-group">
<ExchangeList
exchanges={this.state.exchanges}
selected={this.state.selectedExchange}
// pass the method to a child property (onExchangeSelect)
onExchangeSelect={this.handleOnExchange}
/>
<ExchangeDetail selectedExchange={this.state.selectedExchange} />
</div>
);
}
to use it inside a (class-based) child component, call the method with an arg like this:
this.props.onExchangeSelect(arg)
The reason it can't see it is because you are looking for it in the wrong place. You are looping through the "exchange" props to create a new component so when you reference "this.props.onExchangeSelect", you are not referring the the props passed to the class as you expected but to the exchange object through which you are looping.
To remedy this, consider rewriting the ExchangeContainer component like so:
class ExchangeContainer extends Component {
constructor(props) {
super(props);
this.state = {
exchanges:[
{
name:"binance",
url:"https://bittrex.com"
},
{
name:"bittrex",
url:"https://bittrex.com"
}
],
selectedExchange:"binance"
};
}
setSelectedExchange = (selectedExchange) =>{
this.setState({selectedExchange})
};
render() {
return (
<div className="ExchangeContainer list-group">
<ExchangeList
exchanges={this.state.exchanges} selected={this.state.selectedExchange}
onExchangeSelect={selectedExchange => setSelectedExchange(selectedExchange)}
/>
<ExchangeDetail exchange={this.state.selectedExchange} />
</div>
);
}
}
And the ExchangeList component like so:
class ExchangeList extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
console.log("EL: " + JSON.stringify(this.props));
const {exchanges, selected, onExchangeSelect} = this.props;
const ExItemList = exchanges.map((exchange) => {
return <ExchangeListItem key={exchange.name} exchange={exchange}
onExchangeSelect={onExchangeSelect}/>
});
return (
<ul className="col-md-4 list-group bg-light" >
{ExItemList}
</ul>
);
}
}

React—Change a components state on window.history.popstate

I have a React component that pushes song IDs to the url when the state changes. My problem is that when a user clicks 'back' on their browser, I need to change the state of my SongApp component. How do I do this?
class SongApp extends React.Component {
constructor(props) {
super(props);
this.state = {
song: props.songId
}
this.setSong = this.setSong.bind(this);
}
setSong(e) {
var songId = e.target.id;
this.setState({song: songId})
window.history.pushState({song: songId}, '', '?s='+songId)
}
render() {
var id = this.state.song;
var content = id ? <SongDisplay lyrics={ this.props.songData[id].lyrics } /> : <SongIndex songData={this.props.songData} setSong={this.setSong}/>
return(
<div className="song-app">
{content}
</div>
)
}
}
window.addEventListener('popstate', function(event) {
console.log('popstate fired!');
debugger;
if(event.state.song) {
// change SongApp state
}
});
I found out you can attach the component's method to a listener:
componentDidMount() {
window.addEventListener("popstate", this.setSongFromHistory);
}
setSongFromHistory(e) {
if(e.state.song){
e.preventDefault(); // stop request to server for new html
e.stopPropagation();
this.setState({song: e.state.song});
$('html,body').scrollTop(0);
}
}

How to assign a prop value to a state in react

I have an overlay which is launched from another React component which have a button that also changes itself. The change happens when the user clicks the button, then the button changes it's classname. It also sends a prop value to the children component which is the overlay. The overlay adds a class depending on the property and if it is clicked. Everthing is working pretty nice, but now I have to do another thing. When a user click on the overlay, it have to close up. Before this change, everything was working for the button I mentioned earlier.
Well this is the button component:
export default class StatusBarButton extends React.Component {
constructor(props) {
super(props)
this.state = {active: false}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ active: !this.state.active });
}
render() {
var cx = require('classnames');
var button = cx ({
'statusbar-button-container' : true,
'active' : this.state.active
});
var animation = cx ({
'statusbar-button-cross-image' : true,
'rotate' : true,
'active' : this.state.active
});
return (
<div className="astatusbar-center-wrapper">
<div className={button} onClick={this.handleClick}>
<img src="images/navbar-element-icon-cross.png" className={animation}/>
</div>
<OverlayView isOpen={this.state.active} />
</div>
);
}
}
And this is the Overlay at the moment:
export default class OverlayView extends React.Component {
constructor (props){
super(props);
this.state = {open: false}
this.setState({ open: this.props.isOpen });
}
render() {
var cx = require('classnames');
var overlay = cx({
'overlay': true,
'overlay-slidedown': true,
'open': this.state.open
});
return (
<div className={overlay} onClick={this._closeOverlay}>
<div className="overlay-menu-wrapper">
<OverlayNewInvoiceButton />
<OverlayNewBudgetButton />
<OverlayNewTicketButton />
</div>
</div>
);
}
}
As you see I'm trying to get the prop value and assign it to the state, but it's not working. How can I assign the prop value to the state and use it?
Regards,
JP
You are missing componentWillReceiveProps(props) method in your OverlayView component.
export default class OverlayView extends React.Component {
constructor (props){
super(props);
this.state = {open: props.isOpen}
}
componentWillReceiveProps(props) {
this.setState({open: props.isOpen});
}
render() {
let open = '';
if (this.state.open === true) {
open = 'open';
}
let overlayClass = `overlay overlay-slidedown ${open}`;
return (
<div className={overlayClass} onClick={this._closeOverlay}>
<div className="overlay-menu-wrapper">
<span>{open}</span>
</div>
</div>
);
}
}
Full working example:
https://codesandbox.io/s/35wLR4nA
constructor(props, context) {
super(props, context);
this.state = {
value: ''
};
}
componentWillReceiveProps(){ //this is called to before render method
this.setState({
value:this.props.data
})
You're problem might be that you are trying to fetch the class props with this. I think you are supposed to use the props passed into the constructor.
Like this:
constructor (props){
super(props);
this.state = {open: false}
this.setState({ open: props.isOpen });
}
Not sure why you aren't doing it in one line like this though: this.setState = { open: props.isOpen };
Finally i conserved the property which changes the class, is not bad that way. and i fixed with the help of this: Pass props to parent component in React.js and of course the help of a work mate. the end version is this:
This is the parent:
export default class StatusBarButtonView_Profit extends React.Component {
constructor(props) {
super(props)
this.state = {active: false}
this._openOverlay = this._openOverlay.bind(this)
this._closeOverlay = this._closeOverlay.bind(this)
}
_openOverlay() {
if (this.state.active == false) {
this.setState({ active: true });
console.log('boton lanza overlay');
} else {
this.setState({ active: false });
console.log('boton cierra overlay');
}
}
_closeOverlay(Overlay) {
if (this.state.active == true) {
this.setState({ active: false });
} else {
this.setState({ active: true });
}
}
render() {
var cx = require('classnames');
var button = cx ({
'aui-profit-statusbar-button-container' : true,
'active' : this.state.active
});
var animation = cx ({
'aui-profit-statusbar-button-cross-image' : true,
'rotate' : true,
'active' : this.state.active
});
return (
<div className="aui-profif-statusbar-center-wrapper">
<div className={button} onClick={this._openOverlay}>
<img src="images/aui-navbar-element-icon-cross.png" className={animation}/>
</div>
<OverlayView_Profit isOpen={this.state.active} onClick={this._closeOverlay}/>
</div>
);
}
}
this is the child:
export default class OverlayView_Profit extends React.Component {
constructor (props){
super(props);
}
_closeOverlay() {
this.props.onClick();
}
render() {
var cx = require('classnames');
var overlay = cx({
'aui-overlay': true,
'aui-overlay-slidedown': true,
'open': this.props.isOpen
});
return (
<div className={overlay} onClick={this._closeOverlay.bind(this)}>
<OverlayNewInvoiceButtonView_Profit />
<OverlayNewBudgetButtonView_Profit />
<OverlayNewTicketButtonView_Profit />
</div>
);
}
}
now everything works fine.

Resources