changing Image for Every N seconds , using Hooks in React - reactjs

import React, { useEffect, useState } from 'react'
import styles from './ImageChanging.module.css'
import ArrowLeftIcon from '#mui/icons-material/ArrowLeft';
import ArrowRightIcon from '#mui/icons-material/ArrowRight';
const img1 = require('../../assets/bg1.jpg')
const img2 = require('../../assets/bg2.jpg')
const img3 = require('../../assets/bg3.jpg')
export default function ImageChanging() {
let imageCollection = [img1, img2, img3]
// state
let [displayImageId,setDisplayImageId] = useState(0)
let [displayImage,setDisplayImage] = useState(imageCollection[displayImageId])
// try to reload
useEffect(() => {
setInterval(() => {
changeBg()
}, 8000)
}, [displayImage])
function changeBg() {
console.log(displayImage,"we are seeing the Starting Image")
if (displayImage < imageCollection.length - 1 ) {
setDisplayImageId((prevValue) => prevValue + 1)
setDisplayImage(imageCollection[displayImageId])
}
else {
console.log("we re inside ELse")
setDisplayImageId(0)
setDisplayImage(imageCollection[displayImageId])
}
}
function clickNextImage () {
console.log("U have Clicked Next Image")
if(displayImage == 3 ){
return
}
setDisplayImageId(displayImage + 1)
setDisplayImage(imageCollection[displayImageId])
}
function clickPrevImage() {
console.log("You have Clicked Previous Image")
if(displayImage == 0){
return
}
setDisplayImageId(displayImage - 1)
setDisplayImage(imageCollection[displayImageId])
}
return (
<div className={styles.ImageContainer}>
<ArrowLeftIcon className={styles.IconStyle} onClick={clickPrevImage}/>
<p>{displayImage}</p>
<img className={styles.Image} src={displayImage} />
<ArrowRightIcon className={[styles.IconStyle,styles.IconStyleRight]} onClick={clickNextImage}/>
</div>
)
}
i have imported all my images in my js File
I am running SetInterval inside UseEffect hook , to Change the image in my component
I am getting sometimes displayImageId as 3 and my images are flickring some Times
can Anyone Suggest why Id is gong to 3 what i am doing Wrong

Related

Duplicated setTimeout

When I press the "Buy" button sometimes its grow up correctly and sometimes its just count by 2 clicks. Why this is happening? I am using UseState for change the values and setTimeout for passive increment, so when I press the Buy button its remove the older setTimeout and add a new with the new values.
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import React, { useState, useEffect } from 'react';
var increment = 1000;
var preco = 10;
var total = 0;
function Master() {
const [points, setpoints] = useState(0);
const [Ppoints, setPpoints] = useState(0);
total = points;
function addpoints() {
setpoints((points) => points + 1);
window.clearTimeout(timer);
}
function addPpoints() {
setpoints((points) => points + Ppoints);
}
//passive addiction
let timer = setTimeout(addPpoints, increment);
function passive() {
if (total >= preco) {
setPpoints(Ppoints + 0.5);
setpoints(points - preco);
preco += 10;
window.clearTimeout(timer);
}
}
return (
<>
<h1>{total}</h1>
<button onClick={addpoints}>adicionar</button>
<h1>Price: {preco}</h1>
<button onClick={passive}>Buy</button>
</>
);
}
export default function Home() {
return (
<>
<Master />
</>
);
}

React function on pageload

I want the heartsDisplay function call on pageload, but doing it like that causes an error. It works only with on click. How do I do this in React?
Or maybe there is a way to add default value for hearts in useState hook?
import React, { useState } from 'react'
import './App.css';
var heartsNum = 3;
const App = () => {
const [hearts, setHearts] = useState("");
var Score = 0;
var customColor = {color: 'red'};
const heartsDisplay = () => {
if (heartsNum === 3) {
setHearts("Hearts: ❤❤❤");
} else if (heartsNum === 2) {
setHearts("Hearts: ❤❤");
} else if (heartsNum === 1) {
setHearts("Hearts: ❤");
} else if (heartsNum < 1) {
setHearts("Hearts: ");
}
};
heartsDisplay();
const changeHearts = () => {
heartsNum = heartsNum - 1;
console.log(heartsNum);
heartsDisplay();
}
return (
<div>
<h3 className='hearts'>{hearts}</h3>
<button className='col1' onClick={changeHearts}>Click</button>
</div>
)
}
export default App
useEffect(()=>{
heartsDisplay();
},[]);
Call your function inside useEffect() hook
The useEffect Hook allows you to perform side effects in your components.
Some examples of side effects are: fetching data, directly updating the DOM, and timers.
useEffect accepts two arguments. The second argument is optional.
useEffect(<function>, <dependency>)
https://reactjs.org/docs/hooks-effect.html
import React, { useState } from 'react'
import './App.css';
var heartsNum = 3;
const App = () => {
const [hearts, setHearts] = useState("");
var Score = 0;
var customColor = {color: 'red'};
const heartsDisplay = () => {
if (heartsNum === 3) {
setHearts("Hearts: ❤❤❤");
} else if (heartsNum === 2) {
setHearts("Hearts: ❤❤");
} else if (heartsNum === 1) {
setHearts("Hearts: ❤");
} else if (heartsNum < 1) {
setHearts("Hearts: ");
}
};
call the function inside useEffect hook with no deps to run this function one time to trigger when a change in state or props put that state or props in deps array if you want to trigger the function before unmount return a function in useEffect callback do it in that function if you call the function openly in the component function it will call in all render
useEffect(() => {
heartsDisplay();
},[]);
const changeHearts = () => {
heartsNum = heartsNum - 1;
console.log(heartsNum);
heartsDisplay();
}
return (
<div>
<h3 className='hearts'>{hearts}</h3>
<button className='col1' onClick={changeHearts}>Click</button>
</div>
)
}
export default App
You are misunderstanding the use of useState. Default value for useState is the default value for the hearts variable.
What you are looking for is probably the useEffect hook.
It's default behavior is
similar to componentDidMount and componentDidUpdate
which basically leads to on page load behavior.
import React, { useState, useEffect } from 'react'
import './App.css';
var heartsNum = 3;
const App = () => {
const [hearts, setHearts] = useState("");
var Score = 0;
var customColor = {color: 'red'};
useEffect(() => {
heartsDisplay();
},[]);
const heartsDisplay = () => {
if (heartsNum === 3) {
setHearts("Hearts: ❤❤❤");
} else if (heartsNum === 2) {
setHearts("Hearts: ❤❤");
} else if (heartsNum === 1) {
setHearts("Hearts: ❤");
} else if (heartsNum < 1) {
setHearts("Hearts: ");
}
};
const changeHearts = () => {
heartsNum-=1;
console.log(heartsNum);
heartsDisplay();
}
return (
<div>
<div></div>
<h3 className='hearts'>{hearts}</h3>
<button className='col1' onClick={changeHearts}>Click</button>
</div>
)
}
export default App

useEffect is being called twice even if it state is changed once

i made login hook called "useMakeQueryString". which is responsble for making queryString from Object.
import { useEffect, useState } from "react";
export default function useMakeQueryString(obj) {
const [queryString, setQueryString] = useState("");
const makeQueryString=(obj)=> {
let queryString1 = "";
for (let key in obj) {
//if (key instanceof Object) queryString1 += makeQueryString(obj);
queryString1 += key + "=" + obj[key] + "&";
}
setQueryString(queryString1.slice(0, queryString1.length - 1));
}
useEffect(()=>{
makeQueryString(obj)
},[obj])
return { queryString, makeQueryString };
}
then i imported that hook to my Google Component. on click of Component it calls the performAuth function and that function set the option state. and useEffect on option change is called. inside useEffect which is being called on option change i try to change queryString State. but the problem is useEffect on queryString change is being Called Twice
import useMakeQueryString from "../Login/LoginHook";
import { useEffect,useState } from "react";
export default function Google() {
const g_url = "https://accounts.google.com/o/oauth2/v2/auth";
const {queryString,makeQueryString} = useMakeQueryString({});
let [option,setOption] = useState({})
useEffect(() => {
console.log("length"+Object.keys(option).length)
if(Object.keys(option).length!=0) {
makeQueryString(option); // setQueryString(query);
}
}, [option])
useEffect(()=>{
if(queryString)
window.location = `${g_url}?${queryString}`;
},[queryString])
const performAuth = () => {
console.log("perform cliked")
const option1 = {
client_id: "432801522480-h02v02ivvti9emkd019fvreoisgj3umu.apps.googleusercontent.com",
redirect_uri: "http://localhost:3000/glogin",
response_type: "token",
scope: [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
].join(" "),
}
setOption(option1);
}
return (
<>
<button className="google-btn social-btn" onClick={() => performAuth()}>SignUp With Google</button>
</>
)
}

Calling react hook from a function on another page

I am making a chess game and I need to integrate a count down timer, e.g - so when it's the white players turn their clock is counting down until they move.
To avoid changing a lot more code that is not present in this question ,I would like to keep function "move" as is, though I could change CountDownTimer if needed,
For now I would like to know how to call the react hook setTimerOn in the CountDownTimer component from the function move,then I can work out the rest myself.
From what I have read you cannot do this with react hooks? so just looking for
anything that works, if that means changing CountDownTimer.
export function move(from, to, promotion) {
let tempMove = { from, to }
if (member.piece === chess.turn()) {
const legalMove = chess.move(tempMove)
if (legalMove) {
updateGame()
//i would like to access CountDownTimer and call setTimerOn(true)
// i can work out the code for white and black / start and stop myself afterwards
}
}
,
}
import React from 'react'
function CountDownTimer(){
const [time, setTime] = React.useState(0);
const [timerOn, setTimerOn] = React.useState(false);
React.useEffect(() => {
let interval = null;
if (timerOn) {
interval = setInterval(() => {
setTime((prevTime) => prevTime + 10);
}, 10);
} else if (!timerOn) {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [timerOn]);
return (
<div className="Timers">
<h2>Stopwatch</h2>
<div id="display">
<span>{("0" + Math.floor((time / 60000) % 60)).slice(-2)}:</span>
<span>{("0" + Math.floor((time / 1000) % 60)).slice(-2)}:</span>
<span>{("0" + ((time / 10) % 100)).slice(-2)}</span>
</div>
<div id="buttons">
{!timerOn && time === 0 && (
<button onClick={() => setTimerOn(true)}>Start</button>
)}
{timerOn && <button onClick={() => setTimerOn(false)}>Stop</button>}
{!timerOn && time > 0 && (
<button onClick={() => setTime(0)}>Reset</button>
)}
{!timerOn && time > 0 && (
<button onClick={() => setTimerOn(true)}>Resume</button>
)}
</div>
</div>
);
});
export default CountDownTimer; ```
Based on React documentation, React Hook can be called from function components or other hooks.
In your situation, you should consider the utilization of React Context. You need to move up timerOn state and setTimerOn method as context values. So that, all components which are wrapped by the context provider can utilize the values.
First, create some helpers for managing context.
// TimerOn.js
import React, { createContext, useContext } from 'react';
// create a context
const TimerOnContext = createContext();
// create a hook to provide context value
export function useTimerOn() {
const contextValue = useContext(TimerOnContext);
return contextValue;
}
// custom provider that will wrap your main components
export function TimerOnProvider({ children }) {
const [timerOn, setTimerOn] = React.useState(false);
return (
<TimerOnContext.Provider value={{ timerOn, setTimerOn }}>
{children}
</TimerOnContext.Provider>
);
}
For instance, I create two simple components to demonstrate the timer component and caller component.
// CountDownTimer.js
import React from "react";
import { useTimerOn } from "./TimerOn";
export default function CountDownTimer() {
const { timerOn } = useTimerOn();
// detect changes
React.useEffect(() => {
if (timerOn) {
console.log('timer is on');
} else {
console.log('timer is off');
}
}, [timerOn]);
return (
<div>{timerOn ? 'timer on' : 'timer off'}</div>
);
}
// MoveCaller.js
import React from "react";
import { useTimerOn } from "./TimerOn";
export default function MoveCaller() {
const { timerOn, setTimerOn } = useTimerOn();
// move then set timer
const move = () => {
setTimerOn(!timerOn);
}
return (
<div>
<button type="button" onClick={move}>
Move
</button>
</div>
);
}
Then, you can wrap all main components with the provider component. So, the move function in a component can change the state of timerOn and be read by another component.
import React from 'react';
import CountDownTimer from './CountDownTimer';
import MoveCaller from './MoveCaller';
import { TimerOnProvider } from './TimerOn';
export default function ChessApp() {
return (
<TimerOnProvider>
<CountDownTimer />
<MoveCaller />
</TimerOnProvider>
);
}

Next.js text cycling component never updates

I'm trying to write what I thought would be a simple component: it takes an array of strings, and every three seconds the text in the div of the component is changed to the next item in the array, looping back to the beginning.
Although the console shows that the change message function is run every three seconds, the message never changes. I presume this is because the useState update never happens. Why is this, and how do I get it to work?
// components/textCycle.js
import { useState, useEffect} from 'react';
function TextCycle ( { array } ) {
const [ msg, setMsg ] = useState(0);
useEffect(() => {
function changeMsg() {
setMsg((msg > array.length) ? 0 : msg + 1);
}
setInterval( changeMsg, 3000);
}, []);
return (
<div>
{ array[msg] }
</div>
);
};
export default TextCycle;
// components/textCycle.js
import { useState, useEffect} from 'react';
function TextCycle ( { array } ) {
const [msg, setMsg] = useState(0);
function changeMsg() {
setMsg((msg > array.length - 2) ? 0 : msg + 1);
}
useEffect(() => {
setTimeout(changeMsg, 1000);
}, [msg]);
return (
<div>
{array[msg]}
</div>
);
};
export default TextCycle;

Resources