react-carousel-slider doesn't rerender - javascript

guys! Have a problem with rerendering of slider component. After choosing another SELECT option, other images are to be loaded to carousel component. But!! Nothing happens! Props of component are being changed, and developer tools show slides (images) are changed, but nothing happens on DOM.
Below i post code. What do you think? Where is the problem?
import React from 'react';
import CarouselSlider from "react-carousel-slider";
import { FormControl } from 'react-bootstrap';
class StampChoose extends React.Component {
changeSamplesType = (e) => {
const sampleType = e.target.value;
this.props.changeSamplesType(sampleType);
this.forceUpdate();
}
render() {
let btnWrapperStyle = {
position: "relative",
borderRadius: "50%",
height: "50px",
width: "50px",
textAlign: "center"
}
let btnStyle = {
display: "inline-block",
position: "relative",
top: "90%",
transform: "translateY(-50%)",
fontSize: "36px"
}
let rBtnCpnt = (<div style = {btnWrapperStyle} >
<div style = {btnStyle} className = "material-icons" >
<i className="fas fa-angle-right"></i>
</div>
</div>);
let lBtnCpnt = (<div style = {btnWrapperStyle} >
<div style = {btnStyle} className = "material-icons" >
<i className="fas fa-angle-left"></i>
</div>
</div>);
let iconItemsStyle = {
padding: "0px",
background: "transparent",
margin:"0 5px",
height: "80%"
};
const titles = this.props.titles;
const slides = this.props.slides;
return (
<React.Fragment>
<FormControl componentClass="select" onChange={ this.changeSamplesType }>
<option value="type1">{ titles['type1'] }</option>
<option value="type2">{ titles['type2'] }</option>
<option value="type3">{ titles['type3'] }</option>
<option value="type4">{ titles['type4'] }</option>
</FormControl>
<CarouselSlider
sliderBoxStyle = {{height: "150px", width: "90%", background: "transparent", overflow: "hidden"}}
accEle = {{dots: false}}
newState={ this.state }
slideCpnts = {slides}
itemsStyle = {iconItemsStyle}
buttonSetting = {{placeOn: 'middle-outside'}}
rBtnCpnt = {rBtnCpnt}
lBtnCpnt = {lBtnCpnt}
/>
</React.Fragment>
)
}
}
export default StampChoose;
import React from 'react';
import { Grid, Row, Col, ControlLabel } from 'react-bootstrap';
import { samples, titles} from '../../../samples-stamps';
import StampChoose from './StampChoose';
const Sample = (props) => (
<React.Fragment>
{
<div>
<img src={ `images/samples/${props.img}` } alt={ props.title } />
</div>
}
</React.Fragment>
);
class StampsSamples extends React.Component {
state = {
sampleType: 'type1'
}
changeSamplesType = (sampleType) => {
this.setState({ sampleType });
}
render() {
const sampleType = this.state.sampleType;
let slides = Object.keys(samples[sampleType]).map((item, i) => {
return (
<div>
<Sample
key={i}
title={ samples[sampleType][item].title }
img={ samples[sampleType][item].img }
productId={ samples[sampleType][item].id }
/>
</div>
);
});
return (
<Grid>
<Row>
<Col md={ 4 }>
<ControlLabel>Примерный образец оттиска <br/>
<small>(выберите образец оттиска)</small>
</ControlLabel>
</Col>
<Col md={ 8 }>
<StampChoose
slides={ slides }
titles={ titles }
changeSamplesType={ this.changeSamplesType }
/>
</Col>
</Row>
</Grid>
);
}
}
export default StampsSamples;

In your Sample Component your returning an object inside of React.Fragment. Does it have anything to do with that? What if you remove the { and } inside there and try? Like below. Don't know if thats the issue but try. You also have an extra DIV in your map method for the slides. If you check the instructions for the React Carousel Slider they dont use these extra DIVs and {}
<React.Fragment>
<div>
<img src={ `images/samples/${props.img}` } alt={ props.title } />
</div>
</React.Fragment>

Related

Why does a useCallback option have to be called with a class component in Reactjs?

I am stumped. I have been trying to get a simple cleartext button to work. I have tried all the option available on this platform but nothing is working for me. React Hook useCallback cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook. I have no idea why this error is occurring. I am pretty new to react can anyone please help? I am trying to clear the text on a click of the clear button.
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: ""
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
const handleClick = useCallback(() => {
e.target.value = '';
}, []);
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={handleClick}> Click to clear</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;
It is because you try to use hooks in a class based component. You can only use hooks like useCallback in functional components. Therefore you are mixing the concepts of object oriented and functional programming.
The following should do the trick:
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: ""
};
const handleClick = (e) => {
e.target.value = '';
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={this.handleClick}> Click to clear</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;
useCallback hooks can only be used in functional components OR in a custom Hook NOT in class components.
You have declared your App component in class based approach i.e. Object oriented approach. To use useCallback hook for this, you should change your App component declaration to a functional component or Custom hook.
Something like this
function App() {
return (
<>Hello World!</>
);
}
you cannot useCallBack hook in class Component,we can do a simple thing to clear the button text, by using
a button text state, i.e. { btnTxt: "Clear ButtonText"} than update the state onclick
import React, { Component, useCallback, useState } from "react";
import {
Button,
Input,
Footer,
Card,
CardBody,
CardImage,
CardTitle,
CardText
} from "mdbreact";
import blankImg from "./blank.gif";
import "./style.css";
import "./flags.min.css";
import countriesList from "./countries.json";
class App extends Component {
state = {
search: "",
btnTxt: "Clear ButtonText"
};
renderCountry = country => {
const { search } = this.state;
var code = country.code.toLowerCase();
return (
<div className="col-md-3" style={{ marginTop: "20px" }}>
<Card>
<CardBody>
<p className="">
<img
src={blankImg}
className={"flag flag-" + code}
alt={country.name}
/>
</p>
<CardTitle title={country.name}>
{country.name.substring(0, 15)}
{country.name.length > 15 && "..."}
</CardTitle>
</CardBody>
</Card>
</div>
);
};
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const filteredCountries = countriesList.filter(country => {
return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search Country"
icon="search"
onChange={this.onchange}
/>
<button onClick={()=> this.setState({btnText:""})}> {this.state.btnTExt}</button>
</div>
<div className="col" />
</div>
<div className="row">
{filteredCountries.map(country => {
return this.renderCountry(country);
})}
</div>
</div>
</main>
<Footer color="indigo">
<p className="footer-copyright mb-0">
© {new Date().getFullYear()} Copyright
</p>
</Footer>
</div>
);
}
}
export default App;

TypeError: Cannot read property 'renderView' of null

I am trying to create a main page with 2 buttons in React.js: Option 1 and Option 2. If a user clicks on Option 1, this user should be redirected to Main1 page. If he/she clicks on Option 2, then this user is redirected to Main2. Sounds quite simple, but I get the following error:
TypeError: Cannot read property 'renderView' of null
App.render
C:/test/src/App.js:15
12 |
13 | render() {
14 |
> 15 | switch (this.state.renderView) {
| ^ 16 | case 1:
17 | return (
18 | <div className="App">
This is my code of App.js:
import React, { Component } from 'react';
import './App.css';
import { Header } from './components/Header';
import { Header1 } from './components/xai/Header1';
import { Header2 } from './components/fairness/Header2';
import { Main } from './components/Main';
import { Main1 } from './components/xai/Main1';
import { Main2 } from './components/fairness/Main2';
class App extends Component {
clickBtn = e => {
console.log(e.target.value);
this.setState({
renderView: +e.target.parentNode.value
});
};
render() {
switch (this.state.renderView) {
case 1:
return (
<div className="App">
<div className="App-header">
<Header1 />
</div>
<div className="App-main">
<Main1 />
</div>
</div>
);
case 2:
return (
<div className="App">
<div className="App-header">
<Header2 />
</div>
<div className="App-main">
<Main2 />
</div>
</div>
);
default:
return (
<div className="App">
<div className="App-header">
<Header />
</div>
<div className="App-main">
<Main clickBtn={this.clickBtn} />
</div>
</div>
);
}
}
}
export default App;
This is the code of Main.js where I have two buttons:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Grid from "#material-ui/core/Grid";
import CssBaseline from "#material-ui/core/CssBaseline";
import Card from "#material-ui/core/Card";
import CardContent from "#material-ui/core/CardContent";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles({
card: {
minWidth: 350
},
button: {
fontSize: "12px",
margin: "theme.spacing.unit",
minWidth: 350
},
extendedIcon: {
marginRight: "theme.spacing.unit"
},
title: {
fontSize: '20px',
minWidth: 350,
margin: "theme.spacing.unit"
}
});
export function Main() {
const classes = useStyles();
return (
<React.Fragment>
<CssBaseline />
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center"
style={{ minHeight: "100vh" }}
>
<Card className={classes.card}>
<Typography align="center" className={classes.title}>
Select the option
</Typography>
<CardContent>
<Grid item xs={3}>
<Button
variant="contained"
size="medium"
color="primary"
className={classes.button}
value="1"
onClick={this.props.clickBtn}
>
Option 1
</Button>
</Grid>
<Grid item xs={3}>
<Button
variant="contained"
size="medium"
color="primary"
className={classes.button}
value="2"
onClick={this.props.clickBtn}
>
Option 2
</Button>
</Grid>
</CardContent>
</Card>
</Grid>
</React.Fragment>
);
}
How to fix this issue?
If other classes should be provided here, please let me know.
You didn't create state for the App component:
class App extends Component {
state = {renderView: null}
render(){
...
And note that this.clickBtn is undefined too, so you gotta define it.
since Main.js is a functional component it doesn't include the this keyword.
export function Main(props){
....
onClick={props.clickBtn}

Drag and drop images in React

I'm trying to implement drag and drop behaviour using React JS and react-dropzone library with showing thumbnails.
The code is as follows:
import React from "react";
import ReactDOM from "react-dom";
import Dropzone from "react-dropzone";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dropzone1: [],
dropzone2: []
};
}
addFilesToDropzone(files, dropzone) {
let files_with_preview = [];
files.map(file => {
file["preview"] = URL.createObjectURL(file);
files_with_preview.push(file);
});
const new_files = [...this.state[dropzone], ...files_with_preview];
this.setState({ [dropzone]: new_files });
}
render() {
return (
<div className="App">
<Dropzone
onDrop={files => {
this.addFilesToDropzone(files, "dropzone1");
}}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className="">
<input {...getInputProps()} />
<div style={{ height: 100, backgroundColor: "yellow" }}>
Drop some files here
{dropzone1.map(file => (
<img
src={file.preview}
alt={file.path}
style={{ width: 40, height: 40 }}
/>
))}
</div>
</div>
)}
</Dropzone>
<div style={{ display: "flex", flexDirection: "row", marginTop: 25 }}>
<div style={{ width: "100%" }}>
DROPZONE 2
<Dropzone
onDrop={files => {
this.addFilesToDropzone(files, "dropzone2");
}}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className="">
<input {...getInputProps()} />
<div style={{ height: 100, backgroundColor: "yellow" }}>
Drop some files here
{this.state.dropzone2.map(file => (
<img
src={file.preview}
alt="dsds"
style={{ width: 40, height: 40 }}
/>
))}
</div>
</div>
)}
</Dropzone>
</div>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is the example on codesandbox.
Everything works fine when I drag files from a folder on my computer, but I want to be able to drag thumbnails generated with dropzone 1 to a dropzone 2. But that doesn't work.
Any idea how to do that?
Yes, that doesn't work because that's not what react-dropzone is designed for. Quote from the website,
Simple React hook to create a HTML5-compliant drag'n'drop zone for files.
Use react-dnd or react-beautiful-dnd instead.
You can use another package: react-file-drop

Unable to set zIndex fro autocomplete in reactjs

I am working on a project where i have to implement a search bar which should be in my header component , when ever i try to search the search is working fine but at the same time the search options are overlapping the my content below it. how can i resolve this?
I tried adding zIndex both using css and noraml jsx way both dint work for me bellow is my code.
Header.js
import React, { Component } from 'react';
import Autocomplete from 'react-autocomplete';
import { getStocks, matchStocks } from './data';
class Header extends Component {
state = { value: '' };
render() {
return (
<div style={{ marginTop: 0, marginLeft: 0 }}>
<div className="callout primary" id="Header">
<div className="row column">
<h1>{this.props.name}</h1>
<div style={{ zIndex: 10 }}> // this is where i am trying to set the zIndex
<Autocomplete
classNames={{ autocompleteContainer: 'ac-container' }}
value={ this.state.value }
inputProps={{ id: 'states-autocomplete' }}
wrapperStyle={{ position: 'relative', display: 'inline-block' }}
items={ getStocks() }
getItemValue={ item => item.name }
shouldItemRender={ matchStocks }
onChange={(event, value) => this.setState({ value }) }
onSelect={ value => this.setState({ value }) }
renderMenu={ children => (
<div className = "menu">
{ children }
</div>
)}
renderItem={ (item, isHighlighted) => (
<div
className={`item ${isHighlighted ? 'item-highlighted' : ''}`}
key={ item.abbr } >
{ item.name }
</div>
)}
/>
</div>
</div>
</div>
</div>
);
}
}
export default Header;

How to prevent react component click event bubble to document?

How to prevent react component click event from bubble up to document ?
I can sure that there must be something was wrong with it!
So, may be I should help myself fix it!
I just have a box component which has a click event listener, and there are some link components in that box which are effected by a document click event. How can I remove this document click event?
Can someone do me a favor?
More details info can be found in following links!
Here is the code link : https://github.com/ant-design/ant-design/issues/6576
Click has no effect, it should link to item3!
Remove document's click event
After that, it works!
What's wrong with this?
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import logo from './logo.svg';
import './App.css';
// import SideBox from './SideBox.js';
// import ContentBox from './ContentBox.js';
/*import SidebarExample from './test.js';*/
// import ReactDOMServer from 'react-dom/server';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
import Item1 from './components/Item1.js';
import Item2 from './components/Item2.js';
import Item3 from './components/Item3.js';
import {Menu, Icon} from 'antd';
import 'antd/dist/antd.css';
const SubMenu = Menu.SubMenu;
const element = <h1>Hello, world</h1>;
const elements = () => {
return(
<h1>Hello, world</h1>
);
};
const routes = [
{
path: '/',
exact: true,
sidebar: () => <div>item1</div>,
main: () => <div><Item1 /></div>
},
{
path: '/item2',
sidebar: () => <div>item2</div>,
main: () => <div><Item2 /></div>
},
{
path: '/item3',
sidebar: () => <div>item3</div>,
main: () => <div><Item3 /></div>
}
]
class App extends Component {
constructor(props) {
super(props);
this.state = {
message: props.message,
styles: props.styles,
Any: props.any,
width: props.width,
theme: 'dark',
current: '1'
};
this.handleMenuClick = this.handleMenuClick.bind(this);
this.handleClick = this.handleClick.bind(this);
};
handleClick(e) {
console.log('click ', e);
this.setState({
current: e.key,
});
};
// ES7 property initializer syntax
handleMenuClick = (e) => {
e.preventDefault();
// e.stopPropagation();
// e.nativeEvent.stopImmediatePropagation();
console.log('this is:', this);
console.log("clicked === \n", e);
if(this.state.styles === "App-SideBox-init"){
this.setState({
message: "e.key",
styles: "App-SideBox-New",
width: "width: 40px;"
});
}
if(this.state.styles === "App-SideBox-New"){
this.setState({
message: "Hello!",
styles: "App-SideBox-init",
width: "width: 300px;"
});
}
console.log("this.state.message === ", this.state.message);
console.log("this.state.styles === ", this.state.styles);
};
componentDidMount() {
/*window.addEventListener('scroll', this.onScroll.bind(this), false);*/
// window.removeEventListener('click', this.handleMenuClick.bind(this), false);
// window.removeEventListener('click', this.handleClick.bind(this), false);
};
render() {
return (
<div className="App">
<div className="App-header">
<img id="img" src={logo} className="App-logo" alt="logo" style={this.props.width}/>
<h2>Welcome to React</h2>
</div>
<div className="App-SideBox">
<div className={this.state.styles}>
<Router>
<div>
<div style={{ display: 'flex' }}>
<div style={{
padding: '10px',
width: '30%',
background: '#f0f0f0'
}}>
<div className="SideBox-body" style={{ display: 'flex' }}>
<Menu
theme={this.state.theme}
onClick={this.handleClick}
style={{ width: 240 }}
defaultOpenKeys={['sub1']}
selectedKeys={[this.state.current]}
mode="inline"
>
<SubMenu
key="sub1"
title={
<span>
<Icon type="mail" />
<span>Navigation One</span>
</span>
}
>
<Menu.Item key="1">
<Link to="/"> item1</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/item2">item2</Link>
</Menu.Item>
<Menu.Item key="3">
<Link to="/item3">item3</Link>
</Menu.Item>
</SubMenu>
</Menu>
</div>
</div>
</div>
</div>
</Router>
</div>
{/*onClick={this.handleMenuClick}*/}
<div onClick={this.handleMenuClick} className="App-SideBox-btn">
<span>icon</span>
</div>
</div>
<div className="App-body">
<Router>
<div>
<div>
<div style={{ flex: 1, padding: '10px' }}>
{
routes.map((route, index) => (
<Route
key={index}
path={route.path}
exact={route.exact}
component={route.main}
/>
))
}
</div>
</div>
</div>
</Router>
</div>
</div>
);
}
};
App.defaultProps = {
message: 'Hello!',
styles: 'App-SideBox-init'
};
App.propTypes = {
message: PropTypes.string.isRequired,
styles: PropTypes.string.isRequired,
width: PropTypes.string
};
export default App;
Just make all event handlers on the parent component, and then pass them to children by using props!

Categories