for some reason the value of my setState is not updating when I press the next button. It is for a progress bar where the progress bar adds 20 each time the button is pressed. So like value:this.state.value+20 Does anyone know whats going on? Any help is appreciated. Thanks!
import React, {Component} from "react";
import { Button, Progress } from 'reactstrap';
import "../src/Questions.css"
class Questions extends React.Component {
handleClick=()=>{
alert(this.state.value);
this.setState({
value:this.state.value +20
})
}
render() {
this.state = {
value:10
}
return(
<div>
<div><Progress value={this.state.value} /></div>
<div className="howMuchText">How much does it cost to build an app</div>
<div className="nextButton">
<Button onClick={this.handleClick} color="primary" size="lg">Next</Button>
</div>
</div>
)
}
}
export default Questions;
The reason this is not updating is because you are updating the state using setState in your handleClick function then reseting it in your render function so you are undoing your update. Try this.
Change your source from what you have to this:
import React, { Component } from "react";
import { Button, Progress } from 'reactstrap';
import "../src/Questions.css"
//you've imported component so you don't need to do React.Component
class Questions extends Component {
state = {
value: 10,
}
handleClick = () =>{
alert(this.state.value);
this.setState({
value: this.state.value +20
})
}
render() {
return(
<div>
<div><Progress value={this.state.value} /></div>
<div className="howMuchText">How much does it cost to build an app</div>
<div className="nextButton">
<Button onClick={this.handleClick} color="primary" size="lg">Next</Button>
</div>
</div>
)
}
}
This should do it. Hope this helps.
changing state inside the render function is wrong. At every update, state is going to change. State is immutable at react. You can initialize it inside your constructor function.
constructor(props) {
super(props);
this.state = {
value:10
}
}
You should use constructor to initialize the value. What are you doing wrong in your code when you click button it is updating the value but setState re-render the so it again to initialize value=10.
import React, {Component} from "react";
import { Button, Progress } from 'reactstrap';
import "../src/Questions.css"
class Questions extends React.Component {
constructor(props) {
super(props);
this.state = { value:10
}
}
handleClick=()=>{
alert(this.state.value);
this.setState({
value:this.state.value +20
})
}
render() {
return(
<div>
<div><Progress value={this.state.value} /></div>
<div className="howMuchText">How much does it cost to build an app</div>
<div className="nextButton">
<Button onClick={this.handleClick} color="primary" size="lg">Next</Button>
</div>
</div>
)
}
}
export default Questions;
Related
import React from 'react'
export default () => {
function clickHandler() {
console.log('Button clicked')
}
return (
<div>
<button onClick={clickHandler}>Click</button>
</div>
)
}
In the above code we see that a function has been passed to the onClick.In the same way to the onClick I need to pass a diffrent component which is present in the same src. This component consists of a .js and a .css file.Could you please help me out with it. Thanks in advance
If you don't mind using classes instead of functions, your other component should look like this:
import React from 'react'
class ShowThisAfterClick extends React.Component {
return (
<div>
<p>This is what you want to show</p>
</div>
)
}
export default ShowThisAfterClick
And now you should update the component you've shown:
import React from 'react'
import ShowThisAfterClick from './where/you/put/the/ShowThisAfterClick.js'
class Main extends React.Component {
constructor(props){
super(props)
this.state = { isButtonClicked: false }
this.clickHandler = this.clickhandler.bind(this)
}
clickHandler() {
this.setState({ isButtonClicked: true })
}
render() {
const { isButtonClicked } = this.state
return (
<div>
<button onClick={ this.clickHandler }>Click</button>
{ isButtonClicked ? <ShowThisAfterClick /> : ''}
</div>
)
}
}
export default Main
If you want to keep using functions, then I would kindly suggest to read the manual, it is more than well written.
This is my index.js file
Imports
import React from 'react';
import ReactDOM from 'react-dom';
import field from './images/field.jpg';
import forest from './images/forest.jpg';
import hills from './images/hills.jpg';
import lake from './images/lake.jpg';
import sunrise from './images/sunrise.jpg';
Image component
class Image extends React.Component {
render() {
return (
<div className="img-container">
<img src={this.props.images[this.props.index]} alt={this.props.images[this.props.index]} />
</div>
);
}
}
This is reusable button component
class Button extends React.Component {
render() {
return (
<button className="button" >{this.props.content}</button>
);
}
}
This is two sliders that use button component
class Slider extends React.Component {
render() {
return (
<div className="slider">
<Button content={"❮"} onClick={this.props.decreaseIndex}/>
<Button content={"❯"} onClick={this.props.increaseIndex}/>
</div>
);
}
}
This is the main carousel component that encapsulates all other components
class Carousel extends React.Component {
constructor(props) {
super(props);
this.state = {
images: [field, forest, hills, lake, sunrise],
current: 0
}
}
changeIndex(what){
if (what > 0){
this.setState({
current: (this.state.current+1)%5
});
return;
}
this.setState({
current: (this.state.current-1)%5
});
}
increaseIndex(){
this.changeIndex(1);
}
decreaseIndex(){
this.changeIndex(-1);
}
render() {
return (
<div className="carousel">
<Image index={this.state.current} images={this.state.images}/>
<Slider clickPrev={this.decreaseIndex} clickNext={this.increaseIndex}/>
</div>
);
}
}
ReactDOM.render(<Carousel />, document.getElementById('root'));
I wanted to make a simple carousel using reactjs. It displays one image at a time, previous and next buttons change images. There are total 5 images to be displayed. On clicking 'next' or 'previous' button, images do not change as expected.
What is the exact mistake I am making here? I am new to react.
You have to bind your method changeIndex and the rest in your constructor. Like this:
constructor(props) {
super(props);
this.state = {
images: [field, forest, hills, lake, sunrise],
current: 0
}
this.changeindex = this.changeIndex.bind(this);
//other methods.
}
Read more in React Docs about events.
It is fixed,
Following changes were made:
Binding methods in constructor of Carousel class. Thanks to tksilicon's answer
In Slider class
<Button content={"❮"} work={this.props.decreaseIndex}/>
<Button content={"❯"} work={this.props.increaseIndex}/>
In Button
<button className="button" onClick={this.props.work}>{this.props.content}</button>
Hello I'm trying to change the state when I click the button and only when the state changes run createBattle() but the state does not change after I click the button.
At the beginning I set the state to false. The button is in Form.js with an event onClick={this.handleClick}. Then the event handleClick should set the state to true and when the state changes createBattle() in Battle.js should render the table.
Please tell me what am I doing wrong ?
Thanks
App.js
import React from "react";
import Titles from "./Components/Title";
import Form from "./Components/Form";
import Battle from "./Components/Battle";
import "./App.css";
class App extends React.Component{
state = {
startPosition : false
}
render(){
return(
<div>
<header>
<div className="meniu"></div>
</header>
<div className="wrapper">
<div className="main">
<div className="container">
<div className="title-container">
<Titles />
<div className="info">
<Form startPosition={this.state.startPosition} />
</div>
</div>
<div className="form-container">
<Battle startPosition={this.state.startPosition}/>
</div>
</div>
</div>
</div>
</div>
);
}
};
export default App;
Battle.js
import React, {Component} from "react";
import Square from "./Square";
class Battle extends Component{
constructor(){
super();
}
createBattle = () => {
let table=[];
for (let i=1; i<=10; i++){
let children = [];
for (let j=1; j<=10; j++){
children.push(<Square />)
}
table.push(<div className="board-row">{children}</div>)
}
return table;
}
render(){
console.log(this.props);
return(
<div className="center">
{this.startPosition && this.props.createBattle()}
</div>
);
}
}
export default Battle;
Form.js
import React from "react";
class Form extends React.Component{
constructor(){
super();
}
handleClick = () =>{
this.setState({
startPosition: true
});
};
render(){
console.log(this.props);
return(
<div>
<button className="button" onClick={this.handleClick}>START</button>
</div>
);
}
};
export default Form;
The state and props of a given component is not shared across other components.
If you need to communicate between components you mostly have 2 different options :
Move state logic to a common parent and pass this state as props in child components (Note that you may also need to pass some functions to allow to interact with this parent state from the child components)
Use a common state, with a framework like Redux (widely used in complex projects)
React does not support sharing of state or props values.
So you should use any of the following
React Redux
AsyncStorage
I am trying to pass a search query from an input in searchBar.js to app.js and then back into its child Video in order to search for a video and play it.
I am not sure what I'm doing wrong, as the video is not updating.
Do I need to rerender the video component or something like that?
I am using the react-youtube module for react integration with the YoutubeAPI.
https://github.com/kdelalic/Shuffle
app.js (parent) class:
import React, { Component } from 'react';
import "../css/app.css";
import Video from "./video";
import TopBar from "./topBar";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
searchQuery: null
};
}
myCallback(dataFromChild) {
this.setState({ searchQuery: dataFromChild });
}
render() {
return (
<div>
<TopBar parentCallBack={this.myCallback}/>
<Video query={this.state.searchQuery} />
</div>
);
}
}
topBar.js class:
import React, { Component } from 'react';
import {Navbar} from 'react-materialize';
import '../css/topBar.css';
import SearchBar from './searchBar'
export default class TopBar extends Component {
myCallback(dataFromChild) {
this.props.parentCallBack(dataFromChild);
}
render() {
return (
<div className="wrapper">
<Navbar className="logo" brand='Shuffle+' right>
<SearchBar callBack={this.myCallback}/>
</Navbar>
</div>
);
}
}
searchBar.js class:
import React, { Component } from 'react';
import {NavItem, Icon} from 'react-materialize';
import '../css/searchBar.css';
export default class SearchBar extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
this.props.callBack(this.state.value);
event.preventDefault();
}
render() {
return (
<div className="wrapper">
<form className="form" onSubmit={this.handleSubmit}>
<label>
<input className="input" type="text" value={this.state.value} onChange={this.handleChange} />
</label>
</form>
<NavItem className="searchButton">
<Icon>search</Icon>
</NavItem>
</div>
);
}
}
This looks relatively ok with one exception.
myCallback(dataFromChild) {
this.props.parentCallBack(dataFromChild);
}
// ...when being used
<SearchBar callBack={this.myCallback}/>
The problem is, when the callBack function is called from the Child, the this of the function is set to the child component.
You have a couple options here when passing a function into a child as a callback.
Bind in property
<SearchBar callBack={this.myCallback.bind(this)}/>
The downside is that the function is copied every time the render function is called.
Bind in constructor
As you've already done, you can bind the this context of the function to the parent in the constructor.
class TopBar extends Component {
constructor() {
// ...
this.myCallback = this.myCallback.bind(this);
}
}
Downside is that it's terse and you have to write this for every function you need to bind to the component.
ES Class Property Arrow Functions
This is my personal favorite. The downside is that you need babel and the stage 2 proposal to transpile your code.
class TopBar extends Component {
myCallback = () => {
// ...
}
render() {
<SearchBar callback={this.myCallback} />
}
}
I made an app with multiple components and want their state to be accessed using parent/main app, I'm not sure how to get it. what i'm trying to do is when i change state in main "App" the component state should change. One of the component is 'checkbox' and now i want to access its state using parent app, I made multiple attempts but not getting it done. my code goes like this..
This is Main 'App' code:
import React, { Component } from 'react';
import Checkbox from './checkbox';
import Radio from './Radio';
import ToggleSwitch from './ToggleSwitch';
import PrimaryButton from './PrimaryButton';
class App extends Component {
onClick(isClicked){
isChecked:true
};
render() {
return (
<div id="form">
<Checkbox
onClick={this.onClick}
/>
<RadioButton
onClick={this.onClick}
/>
</div>
);
}
}
export default App;
The component i want to access goes like this:
import React, { Component } from 'react';
class Checkbox extends Component {
constructor(props){
super(props);
this.state={
isChecked:true
};
};
onCheck(){
this.setState({
isChecked: !this.state.isChecked
});
this.props.isClicked()
};
render() {
return (
<div>
<div
className={this.state.isChecked ? 'checked': 'unchecked'}
onClick={this.onCheck.bind(this)}
>
</div>
</div>
);
}
}
export default Checkbox;
You forgot to bind the onClick event in the app component, try this it will work :
class App extends Component {
onClick(isClicked){
console.log('isClicked', isClicked);
};
render() {
return (
<div id="form">
<Checkbox onClick={this.onClick.bind(this)}/>
</div>
);
}
}
If you already have onClick handler for the Checkbox I don't see why you couldn't just move the state up to the App component and just pass down a callback from there to the Checkbox that will update the parent state. That seems like a more React way to do it, to me.
class App extends Component {
constructor(props){
super(props);
this.state={
isChecked:true
}
}
onClick = (isClicked) => {
this.setState({isChecked: !this.state.isChecked})
}
render() {
return (
<div id="form">
<Checkbox
onClick={this.onClick}
ischecked={this.state.isChecked}
/>
</div>
);
}
}
Component
class Checkbox extends Component {
onCheck(){
this.props.onClick()
}
render() {
return (
<div>
<div
className={this.props.isChecked ? 'checked': 'unchecked'}
onClick={this.onCheck.bind(this)}
>
</div>
</div>
)
}
}