Using useState for a slider - not working - react-hooks

Slider component
SliderItem component
Browser
Can someone help me with this issue?
Im expecting to increase the "currentTab" with + 1 when the button "Next slide" is pressed

Instead of using filter which should be used to filter the items array before map which is responsible for rendering, better check if slide index is current and then render it
for example :
import {useState} from 'react';
export default function App() {
return (
<div className="App">
<Slider/>
</div>
);
}
const items = [
{
id: 1,
title: 'Slide 1',
description: 'Description 1',
image: 'https://picsum.photos/800/400?image=0',
},
{
id: 2,
title: 'Slide 2',
description: 'Description 2',
image: 'https://picsum.photos/800/400?image=1',
},
{
id: 3,
title: 'Slide 3',
description: 'Description 3',
image: 'https://picsum.photos/800/400?image=2',
}];
const Slider = () => {
const [current, setCurrent] = useState(0)
const length = items.length
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1)
}
return (
<section className="slider">
{items
.map((item, index) => {
return (
<div
className={index === current ? 'slide active' : 'slide'}
key={item.id}
>
{index === current && (
<>
<img src={item.image} alt="travel image" className="image" />
<button onClick={nextSlide}>next</button>
</>
)}
</div>
)
})}
</section>
)
}
https://codesandbox.io/s/laughing-wilson-xpdiyg?file=/src/App.js

Related

How to write React code to display data of the array object using useEffect

What I am trying:
Take a random character from the characters array and display its abilities and role
Take other four unique random chars name from the same array and display these as option.
Please note that the options must have the correct answer too
If the guessed character is correct the score should increase by 1 else decrease by 1
Code:
import React, { Fragment, useEffect, useState } from "react";
import "../styles/App.css";
const characters = [
{
id: 1,
name: "Jett",
role: "Duelist",
abilities: ["TailWind", "Cloud Burst", "UpDraft", "Blade Storm"],
},
{
id: 2,
name: "Phoenix",
role: "Duelist",
abilities: ["HotHands", "Blaze", "Curve Ball", "Run It Back"],
},
{
id: 3,
name: "Yoru",
role: "Duelist",
abilities: ["GateCrash", "Fakeout", "Blind Side", "Dimensional Drift"],
},
{
id: 4,
name: "Reyna",
role: "Duelist",
abilities: ["Dismiss", "Leer", "Devour", "Empress"],
},
{
id: 5,
name: "Raze",
role: "Duelist",
abilities: ["Paint Shells", "Boom Bot", "BlastPack", "ShowStopper"],
}
];
const App = () => {
const [currChar, setCurrChar] = useState({
name: "",
role: "",
abilities: [],
options: [],
});
const [score, setScore] = useState(0);
const changeChar = () => {
}
const scoreHandler = (e) => {
};
useEffect(() => {
});
return (
<div id="main">
<div className="container">
<h1 className="header">Guess the Character</h1>
<div className="ques-area">
<div className="score" id='score'>Score: {score}</div>
<h3>The character has the following abilities:</h3>
<h4>Role: {currChar.role}</h4>
{currChar.abilities.join()}
<div className="options">
{currChar.options.map((option) => (
<button onClick={scoreHandler}>
{option.name}
</button>
))}
</div>
</div>
</div>
</div>
);
};
export default App;
useEffect(() => {
getRandomObject(characters);
}, []);
const [score, setScore] = useState(0);
const getRandomObject = (array) => {
const optionArr = [];
for (let i = 0; i < array.length; i++) {
optionArr.push(array[Math.floor(Math.random() * array.length)]);
}
const randomObject = array[Math.floor(Math.random() * array.length)];
const obj = {
name: randomObject.name,
role: randomObject.role,
abilities: randomObject.abilities,
options: optionArr.slice(0, 4)
};
setCurrChar(obj);
};

Song overlapping the previous one

Playing.js
import { useEffect, useState, useMemo } from "react";
function Playing(props) {
const [pauseToggle, setpauseToggle] = useState(false);
const [song, setSong] = useState('CKay - Love Nwantiti');
const [src, setSrc] = useState(require(`./Resources/Songs/${song}.mp3`));
useEffect(()=>{
if(props.currentSong.song == undefined){
console.log('Undefined');
}else{
player();
setSong(props.currentSong.song.song);
setSrc(require(`./Resources/Songs/${song}.mp3`));
}
},[props, song, src]);
const music = useMemo(() => new Audio(src), [src]);
const player = () => {
setpauseToggle(!pauseToggle);
if (pauseToggle) {
music.pause();
} else {
music.play();
}
}
return (
<div className="app">
<div className="section3">
<audio></audio>
<i
onClick={player}
className={pauseToggle ? "fas fa-pause" : "fas fa-play pe-1"}>
</i>
</div>
</div>
);
}
export default Playing;
AllSong.js
const All_Song=[
{
song: 'Balti - Ya Lili feat. Hamouda',
title: 'Thisiz Balti',
image: 1,
isPlaying: false,
isFavourite: false,
},{
song: 'CKay - Love Nwantiti',
title: 'Tik Tok Remix',
image: 2,
isPlaying: false,
isFavourite: false,
},{
song: 'Goosebumps',
title: 'HouseMusicHD',
image: 3,
isPlaying: false,
isFavourite: false,
},
];
{All_Song.map(song=>{
return(
<Link
key={song.image}
to={{
pathname:"/",
state:{songInfo: song}
}}
onClick={() => props.setCurrentSong({song})}
>
<div>{song.song}</div>
</Link>
);
})}
Suppose I play any song in the initial state and after going to the list of allsong and clicking on the next song starts playing that song in the background but it overlaps the previous song and simultaniously plays both the song without pausing the previous song. I basically have only basic knowledge about hooks so I just followed some tutorial regarding the useMemo hook.

Why react 'key' props doesn't work for my below case?

I used both (item.id and index) to show unique "key" but it's never working shows those warning (Each child in a list should have a unique "key" prop). Also all my server get disconnected after a while. So, How do I solve both issue? here is my code..
let details = [
{ id: 0, Name: "Pervej", Age: 20 },
{ id: 1, Name: "Hossain", Age: 21 },
];
const [array, SetArray] = useState(details);
const ClearClick = () => {
SetArray([]);
};
<div className="box">
{array.map((item, index) => {
return (
<>
<h2 key={item.id}>
Name: {item.Name} , Age: {item.Age},
</h2>
</>
);
})}
<button type="button" onClick={ClearClick}>
Clear
</button>
</div>
Because the key should be on the top most element. You can't set props for the empty shorthand <>. But you can set it to <React.Fragment>.
Watch out when using index as keys, though (your ids look indexes). Read this: https://reactjs.org/docs/lists-and-keys.html
So, your code should be:
<div className="box">
{array.map((item, index) => {
return (
<React.Fragment key={item.id}>
<h2>
Name: {item.Name} , Age: {item.Age},
</h2>
</React.Fragment>
);
})}

reducer case set value delayed response

When I dispatch "REMOVE_TODO" on button click it does what I want it to do, the problem I'm having is that when it executes. It doesn't return the correct current array length.
Now when I click an item, it will dispatch "TOGGLE_TODO" which will change the font color and put a line-through the text.
Now while toggled and I click the "Clear Completed" button, it toggles "REMOVE_TODO" and works fine. It removes the items toggled. The problem I'm having is that The number doesn't reflex the current amount of items left in the list when I click the button once..
However if I click the button once more (or however many more times) the number updates to the correct total
This is my app code
import React, { useState, useReducer } from 'react';
import { Reducer } from './reducers/reducer';
import './App.css';
function App() {
const [{ todos, todoCount }, dispatch] = useReducer(Reducer, {
todos: [],
todoCount: 0,
completedCount: 0
});
const [text, setText] = useState("");
return (
<div className="App">
<header className="App-header">
<div>ToDo List [ <span style={{color: '#61dafb', margin: '0px', padding: '0px'}}>{ todoCount }</span> ]</div>
<div>
{ todos.map((todo, index) => (
<div
key={index}
onClick={() => dispatch(
{ type: "TOGGLE_TODO", index }
)}
style={{
fontFamily: 'Tahoma',
fontSize: '1.5rem',
textDecoration: todo.completed ? 'line-through' : "",
color: todo.completed ? '#61dafb' : 'dimgray',
cursor: 'pointer'
}}
>
{ todo.text }
</div>
))
}
<form
onSubmit={e => {
e.preventDefault();
text.length === 0 ? alert("No Task To Add!") : dispatch({ type: "ADD_TODO", text });
setText("");
}}
>
<input
type="text"
name="input"
value={ text }
onChange={e => setText(e.target.value)}
/><br />
<button>
Add
</button>
</form>
<button onClick={() => {dispatch({ type: "REMOVE_TODO" })}}>
Clear Completed
</button>
</div>
</header>
</div>
);
}
export default App;
and this is my reducer code
export const Reducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
todos: [...state.todos, { text: action.text, completed: false, id: Date.now() }],
todoCount: state.todoCount + 1,
completedCount: 0
};
case 'TOGGLE_TODO':
return {
todos: state.todos.map((todo, index) => index === action.index ? { ...todo, completed: !todo.completed } : todo),
todoCount: state.todoCount,
completedCount: 0
};
case 'REMOVE_TODO':
return {
todos: state.todos.filter(t => !t.completed),
todoCount: state.todos.length
}
default:
return state;
};
};
Does anyone have any idea what I'm doing wrong, or what I'm not doing? Thanks in advance!
Remove "todoCount" from reducer, then derive count using "todos":
<div>
ToDo List [{" "}
<span style={{ color: "#61dafb", margin: "0px", padding: "0px" }}>
{todos.filter((todo) => !todo.completed).length}
</span>{" "}
]
</div>
View in CodeSandbox here

I am using antd deign to show select option but select cant read id provided and also cannot update onChange

I am using antd deign to show select option but select cant read id provided and also cannot update onChange.
import React from "react";
const data = {
orgName: "",
orgRegNo: "",
orgType: "",
orgTypes: [
{ id: "1", name: "Vendor" },
{ id: "2", name: "Supplier" },
{ id: "3", name: "Vendor and Supplier" }
]
};
export const MyContextTSX = React.createContext(data);
const Store = (props: any) => {
return (
<MyContextTSX.Provider value={data}>{props.children}</MyContextTSX.Provider>
);
};
export default Store;
//Next page of React signup
const signinData = useContext(MyContextTSX);
const [values, setValues] = useState(signinData);
<Select
id={values.orgTypes.id} //shows error while showing id
// name={values.orgTypes.name}
defaultValue="Choose"
style={{ width: 150 }}
onChange={(value: any) => //cant perform onChange
setValues({ ...value, name: value })
}
>
{values.orgTypes.map((option: any) => (
<Option
key={option.id}
value={option.name}
// onChange={handleChange}
>
{option.name}
</Option>
))}
</Select>
I am using antd deign to show select option but select cant read id provided and also cannot update onChange.
Link to CodeSandbox
There are few issues in your code.
Firstly, you are trying to access id from orgTypes which is an array. Instead you can defined a normal id.
Secondly, You need to have a contextProvider wrapping your App component
Third. You need to update state in the correct format such that you are not updating the data but the selected value. For that you need to have a state for selected value
Relavant code
index.js
ReactDOM(
<Store>
<App />
</Store>,
document.getElementById("root")
);
useForm.js
import { useContext, useState } from "react";
import { MyContextTSX } from "./Store";
const useForm = ({ callback }) => {
const values = useContext(MyContextTSX);
const [selected, setSelected] = useState({});
return { values, selected, setSelected };
};
export default useForm;
Register.js
const Register = () => {
const { values, selected, setSelected } = useForm({});
return (
<React.Fragment>
<Select
id={"select"} //shows error here
defaultValue="Choose"
style={{ width: 150 }}
onChange={(
value: any //what to do here ?
) => setSelected(selected)} //what to do here ?
>
{values.orgTypes.map((option: any) => (
<Option key={option.id} value={option.name}>
{option.name}
</Option>
))}
</Select>
<button onClick={() => console.log(values.orgTypes)}>Test</button>
</React.Fragment>
);
};
There are many problems with your code:
id={values.orgTypes.id} // orgTypes is an array, use values.orgTypes[0].id
---
onChange={(
value: any // value is the Select.Option value
) => setValues({ ...value, name: value })} // What exatcly you trying to do here?
Moreover, you don't specify types (and using Typescript).
Check this working example (Javascript):
const data = {
orgName: '',
orgRegNo: '',
orgType: '',
orgTypes: [
{ id: '1', name: 'Vendor' },
{ id: '2', name: 'Supplier' },
{ id: '3', name: 'Vendor and Supplier' }
]
};
const MyContextTSX = React.createContext(data);
function Signup() {
const signinData = useContext(MyContextTSX);
const [selected, setSelected] = useState();
return (
<div>
<h1>Selected: {selected}</h1>
<Select
defaultValue="Choose"
style={{ width: 150 }}
onChange={value => setSelected(value)}
>
{signinData.orgTypes.map(option => (
<Select.Option key={option.id} value={option.name}>
{option.name}
</Select.Option>
))}
</Select>
</div>
);
}
Demo:
Tweaking little bit #Dennish Vash answer and the signup function can also be written like this
function Signup() {
const signinData = useContext(MyContextTSX);
const [selected, setSelected] = useState();
return (
<div>
<h1>Selected: {selected}</h1>
<Select
defaultValue="Choose"
style={{ width: 150 }}
onChange={value => setSelected(value)}
>
{signinData.orgTypes.map(option => (
<Option value="{option.id}">{option.name}</Option>
))}
</Select>
</div>
);
}
Reference: https://github.dev/ant-design/ant-design/tree/master/components/select/demo

Resources