How to import Formik? - reactjs

port './App.css';
function App() {
return (
<>
<div className='container'>
</div>
</>
);
}
ooooooo iiiiiii lk;jv

import React from 'react'
import { Field, Form, Formik} from 'formik';
function Add() {
return (
<Formik
initialValues={{ email: '', firstName: '', lastName: '', myPassword: '' }}
onSubmit={(values) => {
console.log(values)
}}
>
<Form>
<Field type="email" name="email" placeholder="Email" />
<Field name="lastName" placeholder="Doe" />
<Field name="myPassword" placeholder="Password" type="password" />
<button type="submit">Submit</button>
</Form>
</Formik>
)
}
export default Add

https://codesandbox.io/s/elastic-hill-cmbz1?from-embed=&file=/src/Carousel.css:0-429
// App.js //
import Carousel, { CarouselItem } from "./Carousel"; import gtr1
from './assets/gtr.jpg'
export default function App() { return (
<div className="image">
<img src={gtr1}></img>
<div className="txt">
<h1> HeyyyyY!</h1>
</div>
</div>
</CarouselItem>
</Carousel>
</div> ); }
// Carousel.js //
import React, { useEffect, useState } from "react"; import {
useSwipeable } from "react-swipeable";
import "./Carousel.css";
export const CarouselItem = ({ children, width }) => { return (
<div className="carousel-item" style={{ width: width }}>
{children}
); };
const Carousel = ({ children }) => { const [activeIndex,
setActiveIndex] = useState(0); const [paused, setPaused] =
useState(false);
const updateIndex = (newIndex) => {
if (newIndex < 0) {
newIndex = React.Children.count(children) - 1;
} else if (newIndex >= React.Children.count(children)) {
newIndex = 0;
}
setActiveIndex(newIndex); };
useEffect(() => {
const interval = setInterval(() => {
if (!paused) {
updateIndex(activeIndex + 1);
}
}, 3000);
return () => {
if (interval) {
clearInterval(interval);
}
}; });
const handlers = useSwipeable({
onSwipedLeft: () => updateIndex(activeIndex + 1),
onSwipedRight: () => updateIndex(activeIndex - 1) });
return (
<div
{...handlers}
className="carousel"
onMouseEnter={() => setPaused(true)}
onMouseLeave={() => setPaused(false)}
>
<div
className="inner"
style={{ transform: translateX(-${activeIndex * 100}%) }}
>
{React.Children.map(children, (child, index) => {
return React.cloneElement(child, { width: "100%" });
})}
<button
onClick={() => {
updateIndex(activeIndex - 1);
}}
>
Prev
{React.Children.map(children, (child, index) => {
return (
<button
className={${index === activeIndex ? "active" : ""}}
onClick={() => {
updateIndex(index);
}}
>
{index + 1}
);
})}
<button
onClick={() => {
updateIndex(activeIndex + 1);
}}
>
Next
); };
export default Carousel;
// Carousel.css //
*{ margin: 0; } .carousel {
overflow: hidden; }
.inner {
white-space: nowrap;
transition: transform 1s; }
.carousel-item {
display: inline-flex;
align-items: center;
justify-content: center;
color: #fff; }
.indicators {
display: flex;
justify-content: center; }
.indicators > button {
margin: 5px; }
.indicators > button.active {
background-color: green;
color: #fff; }
.image img{
width: 100%;
height: 700px;
position: relative;
display: flex;
align-items: center;
text-align: center;
justify-content: center; } .image{
position: relative;
display: flex;
} .txt{
position: absolute;
display: flex;
justify-content: center;
text-align: center;
width: 100%;
height: 700px;
align-items: center;
} .txt h1{
font-size: 30px;
color: aqua;
margin-bottom: 200px; }

Related

After removing the text area, not able to add again or add other options in a react app

On click on the Text Area, button should add relevant text area in a pag. By clicking on the close button, system should remove the added textarea in a React page. By default, the close button shouldn't display. In this example, system is adding the text area, but once it is removed, I am not able to add the textarea anymore. Could someone please advise the issue here.
CSB link:
https://codesandbox.io/s/nervous-currying-jojdhi?file=/src/App.js
import "./styles.css";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
export default function App() {
const [multiInput, setMultiInput] = useState("");
const [createCode, setCreateCode] = useState("");
const [createImageTag, setImageTag] = useState("");
const [visible, setVisible] = useState(true);
const createCodeSection = () => {
const newElement = React.createElement("blockquote", {
contenteditable: "true",
className: "codehighlight",
name: "codesection" + new Date().getTime()
});
setCreateCode((createCode) => [...createCode, newElement]);
};
const createMultilineTextSection = () => {
const newElement = React.createElement("textarea", {
contenteditable: "true",
className: "defaultTextArea",
name: "textarea" + new Date().getTime()
});
setCreateCode((multiInput) => [...multiInput, newElement]);
};
const createImageSection = () => {
const newElement = React.createElement("img", {
key: "ele" + new Date().getTime()
});
setCreateCode((createImageTag) => [...createImageTag, newElement]);
};
const removeElement = () => {
setVisible((prev) => !prev);
};
return (
<div id="App">
<div className="adminSection">
<div className="row">
<div className="logout"></div>
<div className="createBlogSection">
<div className="row">
<button onClick={createMultilineTextSection}>Text Area</button>
<button onClick={createCodeSection}>Code</button>
<button>Image</button>
</div>{" "}
<br></br>
<div className="row">
<textarea className="defaultTextArea"></textarea>
</div>
<br></br>
<div className="row">
{visible && <span className="dtextArea">{createCode}</span>}
</div>
<div className="row">
{visible && (
<div>
<span className="closeElement">
<button onClick={removeElement}>X</button>
</span>
<span>{multiInput}</span>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
}
//css
.App {
font-family: sans-serif;
text-align: center;
}
.adminSection {
width: 100%;
}
.adminSection h1 {
margin: 25px 0px 0px 550px !important;
color: black !important;
}
.logout img {
height: 30px;
width: 30px;
margin: -100px 50px 0px 0px;
float: right;
}
.createBlogSection {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(700px, 1fr));
grid-gap: 25px !important;
margin: 100px 20px 10px 20px !important;
/* border: solid 1px; */
border-color: #e2e8f0;
border-radius: 0px 5px 5px 0px !important;
background-color: #fff;
}
.defaultTextArea {
height: 100px;
width: 300px;
margin: 10px 0px 10px 40px;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
background-color: #fff !important;
}
.codehighlight {
width: 100%;
color: #fff;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
background-color: #353232 !important;
}
.closeElement {
margin-left: 320px;
display: none;
}
Instead of how you've put the added elements, use:
const removeElement = (index) => {
const newElements = multiInput.filter((_, i) => i == index);
setMultiInput(newElements);
};
// Inside "return" (createBlogSection div)
multiInput.map((_input, index) => {
<div key={index}>
{_input}
<span className="closeElement">
<button onClick={removeElement(index)}>X</button>
</span>
</div>
})
Edit:
Add const [multiInput, setMultiInput] = useState([]); and instead of pushing new elements into separate variables add all into multiInput only. Using setMultiInput(multiInput) => [...multiInput, newElement]); in each case.

REACT creating a basic application where I can set a value

I am very new to REACT and I followed a tutorial where I create a generic app where you can increase / decrease the value.
the html:
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat:400,400i,700">
<!-- Code by Angela Delise
https://codepen.io/angeladelise/pen/zYKpRqE
-->
</head>
<body>
<div id="root"></div>
</body>
the css:
/* color variables */
$clr-negative: #ff1744;
$clr-positive: #2abf77;
$clr-gray100: #f0f7f8;
$clr-gray200: #cfd8dc;
$clr-gray300: #a7b7be;
$clr-gray400: #6b7e86;
$clr-gray500: #425a65;
/* border radius */
$radius: 0.2rem;
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.app {
font-family: Montserrat, sans-serif;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 2rem;
height: 100vh;
background-color: $clr-gray100;
color: $clr-gray500;
}
h1 {
font-size: 6rem;
}
.button__wrapper {
display: flex;
gap: 1rem;
& > * {
border: none;
background-color: white;
box-shadow: 0px 0px 10px $clr-gray200;
font-weight: bold;
font-size: 2rem;
color: inherit;
border-radius: 50%;
outline: none;
height: 4rem;
width: 4rem;
cursor: pointer;
transition: background-color 250ms ease-in-out, transform 50ms ease-in-out;
&:hover {
background-color: $clr-gray200;
}
&:active {
transform: scale(0.9);
}
&:focus {
box-shadow: 0 0 0 3px $clr-gray500;
}
}
}
.negative {
color: $clr-negative;
animation: pulse 500ms ease-in-out;
}
.positive {
color: $clr-positive;
animation: pulse 500ms ease-in-out;
}
#keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
}
JS:
const { useState } = React;
function App() {
const [count, setCount] = useState(0);
return (
<div className="app">
{
// if else statement to determine color of the counter
}
<h1 className={count > 0 ? "positive" : count < 0 ? "negative" : null}>
{count}
</h1>
<div className="button__wrapper">
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
I modify/build from this code and add a text box where I can enter my own value from where it will start from and then have an additional button that I can click to assign that value.
I am not entirely sure on how to implement this feature
If you have to assign the value from the input then you should use uncontrolled input and get the value of the input using useRef hook on button click.
Live Demo
export default function App() {
const inputRef = useRef(); // CHANGE
const [count, setCount] = useState(0);
const assignCustomInput = () => { // CHANGE
const value = inputRef.current.value;
setCount(+value);
};
return (
<div className="app">
<div className="custom-input-wrapper"> // CHANGE
<input type="number" ref={inputRef} />
<button onClick={assignCustomInput}>Assign</button>
</div>
<h1 className={count > 0 ? "positive" : count < 0 ? "negative" : null}>
{count}
</h1>
<div className="button__wrapper">
<button onClick={() => setCount((count) => count - 1)}>-</button>
<button onClick={() => setCount((count) => count + 1)}>+</button>
</div>
</div>
);
}
So you have to create an controlled input for that as shown in below:
const { useState } = React;
function App() {
const [count, setCount] = useState(0);
const handleChange = (evt) => {
setCount(evt.target.value)
}
return (
<div className="app">
{
// if else statement to determine color of the counter
}
<input type="number" value={count} onChange={handleChange} />
<h1 className={count > 0 ? "positive" : count < 0 ? "negative" : null}>
{count}
</h1>
<div className="button__wrapper">
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));

Input checkbox didn't work what I expected

I tried to make an input checkbox when I click the input checkbox, it should be displayed a check image like this.
However, it didn't show the checkbox and I am not sure how to check that the input box was checked or not. Could you help me with what part do I missed and where is something wrong?
I really appreciate your help!
This is CSS inputl and label part
.colors {
display: flex;
flex-direction: column;
span {
margin-bottom: 20px;
}
.colorLists {
margin-left: 10px;
display: flex;
flex-wrap: wrap;
.colorLayout {
display: flex;
flex-direction: column;
position: relative;
width: 33%;
height: 80px;
flex-shrink: 0;
align-items: center;
justify-content: center;
.checkboxLabel {
background-color: beige;
border: 1px solid #ccc;
border-radius: 50%;
cursor: pointer;
height: 28px;
left: 0;
position: absolute;
top: 40;
width: 28px;
&:after {
border: 2px solid #fff;
border-top: none;
border-right: none;
content: '';
height: 6px;
left: 7px;
opacity: 0;
position: absolute;
top: 8px;
transform: rotate(-45deg);
width: 12px;
// opacity: 0.2;
}
}
input[type='checkbox'] {
visibility: hidden;
}
input[type='checkbox']:checked {
& + label {
background-color: beige;
border-color: beige;
&:after {
opacity: 1;
}
}
}
.productColor {
margin-top: 70px;
font-size: 13px;
margin-right: 21px;
}
}
}
}
.sizes {
.HorizontalLine {
margin-top: 25px;
}
.span {
}
.sizeLists {
margin-top: 20px;
margin-bottom: 20px;
button {
margin: 5px;
width: 44px;
height: 32px;
background-color: white;
border: 1px solid silver;
border-radius: 15%;
}
}
}
This is js part
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input type="checkbox" />
<label
className="checkboxLabel"
for="checkbox"
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
In react you have to set the htmlFor property for the label instead of for.
The value should be the same as the id from the input.
Then you can add a value property for the input which is used for adding/removing the item in the list of selected items.
For this purpose a handleChange function can be defined.
const [selectedItems, setSelectedItems] = useState([]);
function handleChange(e) {
let newSelected = [];
if (selectedItems.includes(e.target.value)) {
newSelected = selectedItems.filter((item) => item !== e.target.value);
} else {
newSelected = [...selectedItems, e.target.value];
}
setSelectedItems(newSelected);
}
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
EDIT: Since you are using a class component it can be rewrittenlike this:
export default class CheckboxListComponent extends Component {
constructor(props) {
super(props);
this.state = { selectedItems: [] };
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
let newSelected = [];
if (this.state.selectedItems.includes(e.target.value)) {
newSelected = this.state.selectedItems.filter(
(item) => item !== e.target.value
);
} else {
newSelected = [...this.state.selectedItems, e.target.value];
}
this.setState({ selectedItems: newSelected });
}
render() {
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={this.handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={this.state.selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
}
}
You must tell react that your input is checked so that your CSS will apply it. selected ids must be kept in a place for future existence check. in the following code, I named this array selecetedIdx.
You also need to add idx on selection(via onChange event handler) or wrap them all in form and add them via extra dom attribute.
class Main extends Component {
// initialize selectedIdx with [] in your state (esp constructor)
// e.g. this.state = {/* rest of state, */ selectedIdx: []}
render() {
return (
{COLOR_LISTS.map((color, idx) => {
return (
// ...
<input
type="checkbox"
checked={selectedIdx.includes(idx)}
onChange={() => this.setState(state => ({
selectedIdx: [...state.selectedIdx, idx]
}))}
/>
// ...
)}
)
}
Your checkbox element needs name and value properties and would normally be a child of the <form> element.

React how to repopulate values when back button clicked

In react js i get value from api then i used component to populated vale after back button clicked i don`t want to remove my value i want to my current data that work in text filed but it not work on
select it always remove it value.it show error name not defined.
i want repopulate select when clicked back button
import React from 'react';
import styled from 'styled-components';
import Select from 'react-select';
import { useNavigate } from 'react-router-dom';
import { QsrQoreApi, Eats365, StoreHub } from './Sources';
import SourceStoreSelection from './SourceStoreSelection';
import svgs from '../../shared/svgs';
import { Modal, withAuth } from '../../shared';
const StyledSourceSettings = styled.div`
& .header {
display: flex;
height: 5.2rem;
align-items: center;
border-bottom: 0.1rem solid #edf2f7;
}
& .back {
height: 2rem;
width: 2rem;
margin-left: 2rem;
}
& .title {
margin-left: max(1.5rem, calc(((100vw - 21rem) / 2) - 4rem));
width: 21rem;
height: 2rem;
font-size: 1.6rem;
font-weight: 700;
line-height: 2rem;
text-align: center;
color: #2d3748;
}
& .source-form {
padding: 2rem;
display: grid;
grid-template-columns: 1fr;
}
& .login {
width: 28rem;
margin: 0 auto 0.4rem auto;
font-size: 1.6rem;
font-weight: 700;
color: #2d3748;
}
& .form-input {
margin: 1.5rem auto 0 auto;
width: 28rem;
font-size: 1.6rem;
color: #4a5568;
}
& .form-input > .input {
width: 28rem;
margin: 0.5rem 0 0 0;
height: 3.6rem;
font-size: 1.6rem;
border: 0.1rem solid #a0aec0;
border-radius: 0.4rem;
color: #4a5568;
padding: 1rem;
}
& .form-input > .select {
margin: 0.5rem 0 0 0;
}
& .buffer-152px {
height: 15.2rem;
}
& .buffer-91px {
height: 9.1rem;
}
& .selected-store {
width: 28rem;
height: 2rem;
margin: 2rem auto 0 auto;
font-size: 1.6rem;
font-weight: 700;
color: #2d3748;
}
& .selected-store-detail {
display: flex;
height: 5.1rem;
margin: 0 auto;
align-items: center;
border-bottom: 0.1rem solid #edf2f7;
font-size: 1.6rem;
color: #4a5568;
}
& .selected-store-detail > .map {
height: 2rem;
width: 2rem;
}
& .selected-store-detail > .name {
height: 2rem;
width: 22rem;
margin-left: 1rem;
}
& .selected-store-detail > .forward {
height: 2rem;
width: 2rem;
margin-left: 1rem;
}
& .next-btn {
width: 28rem;
height: 3.6rem;
margin: auto;
margin-top: max(5.3rem, calc(100vh - 47.1rem));
border: 0.1rem solid #cbd5e0;
border-radius: 0.4rem;
background: #ffffff;
box-shadow: 0rem 0.2rem 0.4rem rgba(24, 39, 75, 0.12);
padding: 1rem;
font-size: 1.6rem;
font-weight: 600;
color: #4a5568;
}
& .next-btn:disabled,
& .next-btn[disabled] {
box-shadow: none;
color: #cbd5e0;
}
`;
const sourceOpts = [
{ value: 'QsrQoreApi', label: 'QsrQoreApi' },
{ value: 'Eats365', label: 'Eats365' },
{ value: 'StoreHub', label: 'StoreHub' },
];
const sourceSelectStyles = {
control: (provided) => ({
...provided,
width: '28rem',
minHeight: '3.6rem',
height: '3.6rem',
fontSize: '1.6rem',
border: '0.1rem solid #a0aec0',
borderRadius: '0.4rem',
color: '#4a5568',
}),
indicatorSeparator: () => {},
singleValue: (provided) => ({
...provided,
color: '#4a5568',
}),
valueContainer: (provided) => ({
...provided,
padding: '0.2rem 0.8rem',
}),
placeholder: (provided) => ({
...provided,
margin: 'auto 0.2rem',
}),
input: (provided) => ({
...provided,
margin: '0.2rem',
padding: '0.2rem auto',
}),
dropdownIndicator: (provided) => ({
...provided,
'& svg': {
height: '2rem',
width: '2rem',
},
}),
indicatorsContainer: (provided) => ({
...provided,
'& > div': {
padding: '0.8rem',
},
}),
menu: (provided) => ({
...provided,
borderRadius: '0.4rem',
margin: '0.8rem auto',
}),
menuList: (provided) => ({
...provided,
maxHeight: '30rem',
padding: '0.4rem 0',
}),
option: (provided) => ({
...provided,
padding: '0.8rem 1.2rem',
}),
};
function AddSource(props) {
const { setForm, store, setStore , source} = props;
const [sourceAdditionalInfos, setSourceAdditionalInfos] = React.useState({});
const [sourceStore, setSourceStore] = React.useState(null);
const [showModal, setShowModal] = React.useState(false);
const navigate = useNavigate();
React.useEffect(() => {
if(store.source){
const infos = store.source.additionalInfos.reduce((result, { key, value }) => {
const temp = result;
temp[key] = value;
return temp;
}, {});
setSourceAdditionalInfos(infos);
}
},[]);
React.useEffect(() => {
if (store.source) {
const infospos = store.source.type
const value = infospos;
setSourceStore(value);
}
},[]);
const onBackClick = () => {
navigate(-1);
};
const onSourceSelectChange = (source) => {
if (source) {
setStore({ ...store, source: { type: source.value } });
setSourceStore(null);
}
};
const handleChange = (e) => setSourceAdditionalInfos({ ...sourceAdditionalInfos, [e.target.id]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
if (!sourceStore) setShowModal(true);
else {
const addInfos = Object.entries(sourceAdditionalInfos).map(([k, v]) => ({ key: k, value: v }));
let st = {
...store,
source: {
...store.source,
...sourceStore.value,
additionalInfos: addInfos.concat(sourceStore.value.additionalInfos),
},
};
setStore(st);
setForm('addStore');
}
};
let renderSource = <div className="buffer-152px" />;
if (store.source) {
switch (store.source.type) {
case 'QsrQoreApi':
renderSource = (
<QsrQoreApi
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
case 'Eats365':
renderSource = (
<Eats365
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
case 'StoreHub':
renderSource = (
<StoreHub
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
default:
renderSource = <div className="buffer-152px" />;
break;
}
}
let renderSelectedSourceStore = '';
if (sourceStore) {
renderSelectedSourceStore = (
<>
<div className="selected-store">Store selection</div>
<div className="selected-store-detail" onClick={() => setShowModal(true)}>
<img src={svgs.map} className="map" alt="map" />
<div className="name">{sourceStore.value.name}</div>
<img src={svgs.forward} className="forward" alt="forward" />
</div>
</>
);
} else {
renderSelectedSourceStore = <div className="buffer-91px" />;
}
return (
<StyledSourceSettings>
<div className="header">
<img src={svgs.back} className="back" alt="back" onClick={onBackClick} />
<div className="title">POS System</div>
</div>
<form className="source-form" onSubmit={onSubmit}>
<div className="login">Login credentials</div>
<label className="form-input" htmlFor="type">
<div className="label">POS System</div>
<div className="select">
<Select
options={sourceOpts}
styles={sourceSelectStyles}
placeholder="Choose one"
onChange={onSourceSelectChange}
inputId="type"
isDisabled={sourceStore}
/>
</div>
</label>
{renderSource}
{renderSelectedSourceStore}
<input className="next-btn" type="submit" value="NEXT" disabled={!(store.source && store.source.type)} />
</form>
<Modal onClose={() => setShowModal(false)} open={showModal}>
<SourceStoreSelection
onSubmitted={() => setShowModal(false)}
onClosed={() => setShowModal(false)}
store={store}
sourceAdditionalInfos={sourceAdditionalInfos}
sourceStore={sourceStore}
setSourceStore={setSourceStore}
/>
</Modal>
</StyledSourceSettings>
);
}
export default withAuth(AddSource);
<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>
enter image description here
Try to change it to:
{sourceStore?.value?.name}

How would this React code look without React-hooks and with class components rather than functional components?

I just studied React from YouTube lessons, and there all the lessons were built on classes and the usual this.setState, without hooks. How would this React code look without React-hooks and with class components rather than functional components?
The code itself implements an image slider:
React:
function Slider({ items }) {
const [ active, setActive ] = React.useState(0);
const { length, [active]: slide } = items;
const next = e => setActive((active + +e.target.dataset.step + length) % length);
const goTo = e => setActive(+e.target.dataset.index);
React.useEffect(() => {
const timeout = setTimeout(() => setActive((active + 1 + length) % length), 5000);
return () => clearTimeout(timeout);
}, [active, length]);
return (
<div>
<div className="slideshow-container">
<div className="mySlides fade">
<div className="numbertext">{active + 1} / {length}</div>
<img src={slide.img} />
<div className="text">{slide.title}</div>
</div>
<a className="prev" onClick={next} data-step={-1}>❮</a>
<a className="next" onClick={next} data-step={+1}>❯</a>
</div>
<div className="dots">
{items.map((n, i) => (
<span
key={n.id}
className={`dot ${i === active ? 'active' : ''}`}
onClick={goTo}
data-index={i}
></span>
))}
</div>
</div>
);
}
const items = [
{ title: 'One', img: 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Purity_of_nature.jpg' },
{ title: 'Two', img: 'https://mairie-balma.fr/wp-content/uploads/2016/06/Lhers.jpg' },
{ title: 'Three', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRt-b1iBqHQ_emkm1wFmkM7KQskzIqg7YQPZWW85Sa7k2nNLwgjMw' },
].map((n, i) => ({ ...n, id: i + 1 }));
ReactDOM.render(<Slider items={items} />, document.getElementById('app'));
HTML
<div id="app"></div>
CSS:
.slideshow-container {
max-width: 500px;
position: relative;
margin: auto;
}
.prev, .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
.prev:hover, .next:hover {
background-color: rgba(0,0,0,0.8);
}
.text {
color: #f2f2f2;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
box-sizing: border-box;
}
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
.dots {
display: flex;
justify-content: center;
}
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
.mySlides img {
width: 100%;
}
Something like this (not fully tested):
class Slider {
constructor(props) {
super(props);
this.state = {
active: 0
}
}
let timeout = null;
componentDidMount() {
this.timeout = setTimeout(() => this.setActive(), 5000);
}
componentDidUpdate(prevProps) {
const { active } = this.props;
if (prevProps.active !=== active {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => this.setActive(), 5000);
});
}
componentDidUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
const setActive = (newActive) => {
const { length } = items;
this.setState({
active: (newActive + 1 + length) % length
});
}
const next = e => {
const { length } = items;
this.setActive((this.state.active + +e.target.dataset.step + length) % length);
}
const goTo = e => this.setActive(+e.target.dataset.index);
render() {
const { length } = items;
const {active} = this.state;
return (
<div>
<div className="slideshow-container">
<div className="mySlides fade">
<div className="numbertext">{active + 1} / {length}</div>
<img src={slide.img} />
<div className="text">{slide.title}</div>
</div>
<a className="prev" onClick={this.next} data-step={-1}>❮</a>
<a className="next" onClick={this.next} data-step={+1}>❯</a>
</div>
<div className="dots">
{items.map((n, i) => (
<span
key={n.id}
className={`dot ${i === active ? 'active' : ''}`}
onClick={this.goTo}
data-index={i}
></span>
))}
</div>
</div>
);
}
}
const items = [
{ title: 'One', img: 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Purity_of_nature.jpg' },
{ title: 'Two', img: 'https://mairie-balma.fr/wp-content/uploads/2016/06/Lhers.jpg' },
{ title: 'Three', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRt-b1iBqHQ_emkm1wFmkM7KQskzIqg7YQPZWW85Sa7k2nNLwgjMw' },
].map((n, i) => ({ ...n, id: i + 1 }));
ReactDOM.render(<Slider items={items} />, document.getElementById('app'));

Resources