React Carousel: Previous and Next buttons aren't working - javascript

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>

Related

How to pass component to onClick in react

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.

Display a new component with button click

Im making my first react ptoject. Im new in JS, HTML, CSS and even web app programing.
What i try to do, is to display some infomration on button click.
I have an API, that looks like this:
endpoint: https://localhost:44344/api/Projects
My Data from it:
[{"id":1,"name":"Mini Jira","description":"Description for first project in list","tasks":null},{"id":2,"name":"Farm","description":"Description for second one","tasks":null}]
And im fine with that, i can get it easily by axios in my react app.
Now i will show you my Project.js Component:
import React, { Component } from "react";
import { ListGroupItem, Button, ButtonToolbar } from "react-bootstrap";
import ProjectDetails from "./ProjectDetails";
class Project extends Component {
render() {
return (
<ButtonToolbar>
<ListGroupItem>{this.props.project.name}</ListGroupItem>
<Button onClick={Here i want to display new component with details }bsStyle="primary">Details</Button>
</ButtonToolbar>
);
}
}
export default Project;
I have all data from api in project type.
My question is, how to display component that i named ProjectDetails.js on button click? I want to show all data stored in project from my api in separate view (new page or somethig like that).
View looks like this:
Thanks for any advices!
EDIT:
based on #Axnyff answer, i edited Project.js. it works ok. But when i want to (for testing) displat project.name, i get error map of undefined. My ProjectDetails.js:
import React, { Component } from "react";
class ProjectDetails extends Component {
state = {};
render() {
return <li>{this.props.project.name}</li>;
}
}
export default ProjectDetails;
EDIT2:
In Project.js in #Axnyff answet i just edited that line:
{this.state.showDetails && (
<ProjectDetails project={this.props.project} />
)}
i passed project by props, now it works like i want too. After click it displays project.name that i clicked on.
You should use state in your React component.
Let's create a field called showDetails in your state.
You can initialize it in your constructor with
constructor(props) {
super(props); // needed in javascript constructors
this.state = {
showDetails: false,
};
}
Then you need to modify the onClick to set that state to true
<Button onClick={() => this.setState({ showDetails : true })} bsStyle="primary">Details</Button>
And then use that state to show or not the ProjectDetails:
{ showDetails && <ProjectDetails /> }
The full component should look like
import React, { Component } from "react";
import { ListGroupItem, Button, ButtonToolbar } from "react-bootstrap";
import ProjectDetails from "./ProjectDetails";
class Project extends Component {
constructor(props) {
super(props); // needed in javascript constructors
this.state = {
showDetails: false,
};
}
render() {
return (
<ButtonToolbar>
<ListGroupItem>{this.props.project.name}</ListGroupItem>
<Button onClick={() => this.setState({ showDetails : true })} bsStyle="primary">Details</Button>
{ this.state.showDetails && <ProjectDetails /> }
</ButtonToolbar>
);
}
}
export default Project;
You can then modify the logic to add a toggling effect etc.
If you haven't done it, you should probably follow the official tutorial
function Bar() {
return <h1>I will be shown on click!</h1>;
}
class Foo extends React.Component {
constructor() {
super();
this.state = { showComponent: false };
}
handleClick = () => {
this.setState({ showComponent: !this.state.showComponent });
};
render() {
return (
<div>
{this.state.showComponent && <Bar />}
<button onClick={this.handleClick}>click</button>
</div>
);
}
}
ReactDOM.render(<Foo />, 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>

How to deal with this.setState issue in react JS

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;

How to toggle elements with a button press in React?

I have searched for 3 freaking days to find out how to toggle my mobile nav button to toggle my mobile menu. I am new to React and could do this easily with jQuery but I don't want to use jQuery. I have line for line copied an example that I found on how to show or hide an element. I can not get it to work. Any help would be much appreciated. I am using styled-components with React.
Button sub-component:
import React, { Component } from 'react';
class MenuButton extends Component {
render() {
return (
<Button onClick={this.props.toggleMenu}>
<Menu></Menu>
</Button>
)
}
}
export default MenuButton;
Menu sub-component:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Menu extends Component {
render() {
return (
<OffCanvasMenu>
<Title>Menu</Title>
<Nav>
<NavLinks><Link to='/'>Home</Link></NavLinks>
<NavLinks><Link to='/about'>About</Link></NavLinks>
<NavLinks><Link to='/interactive'>Interactive</Link></NavLinks>
<NavLinks><Link to='/ideas'>Ideas</Link></NavLinks>
<NavLinks><Link to='/contact'>Contact</Link></NavLinks>
</Nav>
</OffCanvasMenu>
)
}
}
export default Menu;
Menu Container component with all the state:
import React, { Component } from 'react';
import Menu from './Menu';
import MenuButton from './MenuButton';
class MenuContainer extends Component {
constructor(props) {
super(props);
this.state = {
active: false
}
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu() {
const { active } = this.state;
this.setState({
//toggle value of `active`
active: !active
});
}
render() {
return (
<div>
<MenuButton onClick={this.toggleMenu}/>
{this.state.active && <Menu/>}
</div>
)
}
}
export default MenuContainer;
I can see a checkbox in ReactDev tools that shows MenuContainer has state but when the button is clicked it does not toggle the state.
onClick is handled by MenuButton component which in turns invokes toggleMenu function passed as a property. I would pass toggleMenu as property of MenuButton:
<MenuButton toggleMenu={this.toggleMenu} />

How to make/access state using props in react?

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>
)
}
}

Categories

Resources