Navigate around navigation bar using key event in react js - reactjs

Hi my problem is I have done a react js web page I have a navigation bar and my default menu is home and I have 4 more menus beside home menu and now I want to apply keyevent to navigate to right and left of the navigation bar amd when i press up and down arrow keys the focus should move to down section of the navigation bar i mean to next div section has i mentioned in home.js the next div is banner of web page and next to banner is row of images(Tvshows component) and so on to navigate through all the div in the page.
Menu.js
import React, { useEffect, useState } from "react";
import { Menudata } from "./Menudata";
import ListItem from "./ListItem";
const useKeyPress = function (targetKey) {
const [keyPressed, setKeyPressed] = useState(false);
function downHandler({ key }) {
if (key === targetKey) {
setKeyPressed(true);
}
}
const upHandler = ({ key }) => {
if (key === targetKey) {
setKeyPressed(false);
}
};
React.useEffect(() => {
window.addEventListener("keydown", downHandler);
window.addEventListener("keyup", upHandler);
return () => {
window.removeEventListener("keydown", downHandler);
window.removeEventListener("keyup", upHandler);
};
});
return keyPressed;
};
const Menu = () => {
const [selected, setSelected] = useState(undefined);
const rightPress = useKeyPress("ArrowRight");
const leftPress = useKeyPress("ArrowLeft");
const [cursor, setCursor] = useState(0);
const [hovered, setHovered] = useState(undefined);
useEffect(() => {
if (Menudata.length && rightPress) {
setCursor((prevState) =>
prevState < Menudata.length - 1 ? prevState + 1 : prevState
);
}
}, [rightPress]);
useEffect(() => {
if (Menudata.length && leftPress) {
setCursor((prevState) => (prevState > 0 ? prevState - 1 : prevState));
}
}, [leftPress]);
useEffect(() => {
if (Menudata.length && hovered) {
setCursor(Menudata.indexOf(hovered));
}
}, [hovered]);
return (
<div className="Menu">
{Menudata.map((item, i) => (
<ListItem
key={item.id}
active={i === cursor}
item={item}
setSelected={setSelected}
setHovered={setHovered}
/>
))}
</div>
);
};
export default Menu;
Menudata.js
export const Menudata = [
{
name:"Home"
},
{
name:"TVshows"
},
{
name:"Originals"
},
{
name:"Movies"
},
{
name:"Sports"
},
{
name:"Premium"
}
]
Home.js
import React from "react";
import Tvshows from "./Tvshows";
import Originals from "./Originals";
const Home= () => {
const home = [
{ src: './images/tamil.jpg' },
{ src: './images/telugu.jpg' },
{ src: './images/malayam.jpg' },
{ src: './images/marathi.jpg' },
{ src: './images/hindi.jpg' },
{ src: './images/english.jpg' },
{ src: './images/bengali.jpg' },
{ src: './images/kannada.jpg' },
];
const largeimg=[
{ src: 'images/Undekhi_web_tray_dated_23march_rev (1).jpg' },
];
return (
<div className="row">
<div className="banner">
<div className="banner__contents">
<h1 className="banner__title"><h1>LIVE</h1> STREAMING</h1>
</div>
</div>
<div>
<Tvshows/>
</div>
<div className="row_images" >
<h1>Watch in your language</h1>
{
home.map((index) => <img src={index.src} alt="" height="180" width="155"></img>)
}
</div>
<div >
<Originals/>
</div>
<div className="row__largeimage" >
{
largeimg.map((index) => <img src={index.src} alt="" ></img>)
}
</div>
</div>
)
}
export default Home;

Related

PayPal Checkout not showing correct total amount in react app

Good morning. I am trying to integrate PayPal check out in my React app. Everything works fine except that the Paypal Checkout amount is not showing the same as the total cart amount. Checkout amount is fixed at $0.01 and not changing as cart amount changes. Please what could i be doing wrong ??? This is the code
#cart.js code
import React, { useContext, useState, useEffect } from "react";
import { GlobalState } from "../../../GlobalState";
import axios from "axios";
import PayPalButton from "./PaypalButton";
function Cart() {
const state = useContext(GlobalState);
const [cart, setCart] = state.userAPI.cart;
const [token] = state.token;
const [total, setTotal] = useState(0);
useEffect(() => {
const getTotal = () => {
const total = cart.reduce((prev, item) => {
return prev + item.price * item.quantity;
}, 0);
setTotal(total);
};
getTotal();
}, [cart]);
const addToCart = async () => {
await axios.patch(
"/user/addcart",
{ cart },
{
headers: { Authorization: token },
}
);
};
const increment = (id) => {
cart.forEach((item) => {
if (item._id === id) {
item.quantity += 1;
}
});
setCart([...cart]);
addToCart();
};
const decrement = (id) => {
cart.forEach((item) => {
if (item._id === id) {
item.quantity === 1 ? (item.quantity = 1) : (item.quantity -= 1);
}
});
setCart([...cart]);
addToCart();
};
const removeProduct = (id) => {
if (window.confirm("Do you want to delete this product?")) {
cart.forEach((item, index) => {
if (item._id === id) {
cart.splice(index, 1);
}
});
setCart([...cart]);
addToCart();
}
};
const tranSuccess = async (payment) => {
console.log(payment);
};
if (cart.length === 0)
return (
<h2 style={{ textAlign: "center", fontSize: "5rem" }}>Cart Empty</h2>
);
return (
<div>
{cart.map((product) => (
<div className="detail cart" key={product._id}>
<img src={product.images.url} alt="" />
<div className="box-detail">
<h2>{product.title}</h2>
<h3>${product.price * product.quantity}</h3>
<p>{product.description}</p>
<p>{product.content}</p>
<div className="amount">
<button onClick={() => decrement(product._id)}> - </button>
<span>{product.quantity}</span>
<button onClick={() => increment(product._id)}> + </button>
</div>
<div className="delete" onClick={() => removeProduct(product._id)}>
X
</div>
</div>
</div>
))}
<div className="total">
<h3>Total: $ {total}</h3>
<PayPalButton total={total} tranSuccess={tranSuccess} />
</div>
</div>
);
}
export default Cart;
PayPal button code
import React from "react";
import { PayPalScriptProvider, PayPalButtons } from "#paypal/react-paypal-js";
export default class PayPalButton extends React.Component {
render() {
const onSuccess = (payment) => {
console.log("The payment was succeeded!", payment);
this.props.tranSuccess(payment);
};
const onCancel = (data) => {
console.log("The payment was cancelled!", data);
};
const onError = (err) => {
console.log("Error!", err);
};
let env = "sandbox"; // you can set here to 'production' for production
let total = this.props.total;
let currency = "USD";
const client = {
sandbox:
"ARhnfWu_QrcGQa-PdvaY1RVriEmqGiSkfEWf-plauZQpQN_gyxaLjH9RXOhdQw7fxxxxxxxxxxxx",
production: "YOUR-PRODUCTION-APP-ID",
};
let style = {
size: "small",
color: "blue",
shape: "rect",
label: "checkout",
tagline: false,
};
return (
<PayPalScriptProvider
options={{
"client-id": "ARhnfWu_QrcGQa-PdvaY1RVriEmqGiSkfEWf-plauZQpQN_gyxaLjH9RXOhdQw7fxxxxxxxxxxxx",
}}
>
<PayPalButtons
env={env}
client={client}
commit={true}
total={total}
currency={currency}
onError={onError}
onSuccess={onSuccess}
onCancel={onCancel}
style={style}
/>
</PayPalScriptProvider>
);
}
}
I don't see a createOrder function anywhere. You need one, and it needs to invoke actions.order.create() with a JSON object that uses your total to set the amount.
See examples in the react-paypal-js storybook.

Betton are not disappear when removing atomFamily recoil.js

Why when user click "remove button" in ListItem component, the item text are disappear but the button itself are still there, if possible how to get rid of that "remove button" too?
P.S The atom family item are got removed but the ui are not get updated ("remove button" are still there), is that a normal things?
import React, {useState} from "react";
import { atom, useRecoilState, useResetRecoilState, useRecoilCallback, atomFamily, useRecoilValue, useSetRecoilState } from "recoil";
import "./styles.css";
const idsState = atom({
key: "circleColor",
default: [],
});
const noteState = atomFamily({
key: "noteState",
default: []
})
const ListItem = ({ id }) => {
const [note, setNote] = useRecoilState(noteState(id));
const handleRemoveNote = useResetRecoilState(noteState(id));
return (
<div key={note.id} className="list-item">
<p>{note.text}</p>
<button onClick={handleRemoveNote}>Remove</button>
</div>
)
}
const App = () => {
const ids = useRecoilValue(idsState);
const nextId = ids.length;
const addNote = useRecoilCallback(({set}) => (newNote) => {
set(idsState, [...ids, nextId])
set(noteState(nextId), newNote);
})
const [text, setText] = useState("");
const handleAddNote = (e) => {
e.preventDefault();
const id = Math.round(Math.random() * 1000);
const newNote = {
text,
id,
subNote: [
{
label: "zero",
value: "0"
},
{
label: "one",
value: "1"
},
{
label: "two",
value: "two"
}
]
};
addNote(newNote);
}
return (
<div>
<form className="form-container" onSubmit={handleAddNote}>
<input onChange={e => setText(e.target.value)} />
<button>Add</button>
</form>
<div>
{ids.map(id => (
<ListItem id={id} />
))}
</div>
</div>
);
};
export default App;

How to console.log the

I have a simple React component and inside of it I am fetching data from a remote API, and I want to console.log it in useEffect. I am trying to do it but nothing doesn't get logged into the console, why? What am I missing here? Here is the component:
import React, { useState, useEffect } from 'react';
import { useLocalization } from '#progress/kendo-react-intl';
import { Card, CardHeader, Avatar, CardTitle, CardSubtitle } from '#progress/kendo-react-layout';
import { guid } from '#progress/kendo-react-common';
import { Scheduler } from './../components/Scheduler';
import { employees } from './../resources/employees';
import { images } from './../resources/images';
import { orders, ordersModelFields } from './../resources/orders';
import { teams } from './../resources/teams';
// const orderEmployees = employees.filter(employee => employee.jobTitle === 'Sales Representative');
// const initialFilterState = { };
// orderEmployees.forEach(employee => {
// if(employee.fullName === 'Wait Peperell') {
// initialFilterState[employee.id] = false;
// } else {
// initialFilterState[employee.id] = true;
// }
// });
const Planning = () => {
const localizationService = useLocalization();
const [filterState, setFilterState] = React.useState(initialFilterState);
const [data, setData] = React.useState(orders);
const [fetchedData, setFetchedData] = React.useState(null);
useEffect(() => {
fetch("https://mocki.io/v1/29b83c0b-1a55-430d-a173-92b3632e04aa")
.then(response => response.json())
// 4. Setting *dogImage* to the image url that we received from the response above
.then(data => setFetchedData(data))
console.log(fetchedData)
},[])
// console.log(fetchedData)
const onDataChange = React.useCallback(
({ created, updated, deleted }) => {
setData(old => old
// Filter the deleted items
.filter((item) => deleted.find(current => current[ordersModelFields.id] === item[ordersModelFields.id]) === undefined)
// Find and replace the updated items
.map((item) => updated.find(current => current[ordersModelFields.id] === item[ordersModelFields.id]) || item)
// Add the newly created items and assign an `id`.
.concat(created.map((item) => Object.assign({}, item, { [ordersModelFields.id]: guid() }))))
},
[]
);
const onEmployeeClick = React.useCallback(
(employeeId) => {
setFilterState({
...filterState,
[employeeId]: !filterState[employeeId]
});
},
[filterState, setFilterState]
);
return (
<div id="Planning" className="planning-page main-content">
<div className="card-container grid">
<h3 className="card-title">{localizationService.toLanguageString('custom.teamCalendar')}</h3>
{
orderEmployees.map(employee => {
return (
<div
key={employee.id}
onClick={() => onEmployeeClick(employee.id)}
style={!filterState[employee.id] ? {opacity: .5} : {}}
>
<Card style={{ borderWidth: 0, cursor: 'pointer'}}>
<CardHeader className="k-hbox" >
<Avatar type='image' shape='circle' size={'large'} style={{
borderWidth: 2,
borderColor: teams.find(({teamID}) => teamID === employee.teamId).teamColor,
}}>
<div className="k-avatar-image" style={{
backgroundImage: images[employee.imgId + employee.gender],
backgroundSize: 'cover',
backgroundPosition: 'center center',
}}
/>
</Avatar>
<div>
<CardTitle style={{color: teams.find(({teamID}) => teamID === employee.teamId).teamColor}}>{employee.fullName}</CardTitle>
<CardSubtitle>{employee.jobTitle}</CardSubtitle>
</div>
</CardHeader>
</Card>
</div>
);
})
}
<div className="card-component" >
<Scheduler
data={data.filter(event => filterState[event.employeeID])}
onDataChange={onDataChange}
modelFields={ordersModelFields}
resources={[
{
name: 'Teams',
data: teams,
field: 'teamID',
valueField: 'teamID',
textField: 'teamName',
colorField: 'teamColor'
}
]}
/>
</div>
</div>
</div>
);
}
export default Planning;
I also tried to place the console.log outside of useEffect but still, nothing gets console.logged.
You need to look how useEffect work, setFetchedData is async.
Create another useEffect only for console.log.
useEffect(() => {
console.log(fetchedData);
},[fetchedData]); // Update at the first render + when fetchedData state change.
You can do it like this
useEffect(() => {
fetch("https://mocki.io/v1/29b83c0b-1a55-430d-a173-92b3632e04aa")
.then((response) => response.json())
// 4. Setting *dogImage* to the image url that we received from the response above
.then((data) => {
setFetchedData(data);
console.log(data);
});
}, []);
or juste create another useEffect that listens to fetchedData change, like this
useEffect(() => {
console.log(fetchedData);
}, [fetchedData]);

Is it a valid way to write redux actions and reducer?

I've built a cards war game. I'm new to redux and wonder if I use it the correct way, especially when I declare actions in the Game and Main components, and use action's payloads as callbacks to update the state. Also, It feels like a lot of code for a small app. Maybe you can help guys and give me some insights if i'm doing it the wrong way and why, thanks. I put here the relevant components and the full code is here:
https://github.com/morhaham/cards-war-redux
store.js:
import { createStore } from "redux";
const state = {
game_ready: false,
cards: [],
player: { name: "", cards: [], points: 0 },
computer: { name: "computer", cards: [], points: 0 },
};
const reducer = (state, action) => {
switch (action.type) {
case "INIT_GAME_CARDS":
return action.payload(state);
case "UPDATE_PLAYER_NAME":
return action.payload(state);
case "SET_GAME_READY":
return action.payload(state);
case "DIST_CARDS":
return action.payload(state);
case "SET_NEXT_CARDS":
return action.payload(state);
case "INCREASE_POINTS":
return action.payload(state);
case "RESET_GAME":
return action.payload(state);
default:
return state;
}
};
const store = createStore(reducer, state);
export default store;
Main.js:
import React, { useEffect } from "react";
import { Button } from "#material-ui/core";
import { useHistory } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { NUM_OF_CARDS, MAX_CARD_VALUE } from "./constants";
import { shuffle } from "./helpers";
// action creator to initialize the game
const initGameCards = () => ({
type: "INIT_GAME_CARDS",
payload: (state) => {
// creates an array of size 52 filled with 1..13 four times
const cards = Array(NUM_OF_CARDS / MAX_CARD_VALUE)
.fill(
Array(13)
.fill()
.map((_, i) => i + 1)
)
.flat();
// shuffle the cards
shuffle(cards);
return {
...state,
cards,
};
},
});
// action creator to control the player's name
const updatePlayerName = (name) => ({
type: "UPDATE_PLAYER_NAME",
payload: (state) => ({
...state,
player: { ...state.player, name: name },
}),
});
const setGameReady = () => ({
type: "SET_GAME_READY",
payload: (state) => ({
...state,
game_ready: true,
}),
});
function Main() {
const history = useHistory();
const dispatch = useDispatch();
const player = useSelector(({ player }) => player);
// const game_ready = useSelector(({ game_ready }) => game_ready);
const handleClick = React.useCallback(
(e) => {
e.preventDefault();
if (player.name) {
dispatch(setGameReady());
history.replace("./game");
}
},
[dispatch, player.name]
);
useEffect(() => {
dispatch(initGameCards());
}, []);
const handleChange = React.useCallback((e) => {
const target = e.target;
const val = target.value;
switch (target.id) {
case "playerName":
dispatch(updatePlayerName(val));
break;
default:
break;
}
});
return (
<div>
{/* check for valid input */}
<form>
<label htmlFor="playerName">
<h1 className="text-blue-800 text-5xl text-shadow-lg mb-3">
Ready for war
</h1>
</label>
<input
className="border focus:ring-2 focus:outline-none"
id="playerName"
required
onChange={handleChange}
placeholder="Enter your name"
type="text"
value={player.name}
/>
{!player.name ? (
<p className="text-red-700">Please fill the field</p>
) : (
""
)}
<Button
onClick={handleClick}
type="submit"
color="primary"
variant="contained"
>
Start
</Button>
</form>
</div>
);
}
export default Main;
Game.js:
import { Button } from "#material-ui/core";
import React from "react";
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useHistory } from "react-router-dom";
import { NUM_OF_CARDS } from "./constants";
import { shuffle } from "./helpers";
// action creator to distribute the cards at the beginning of the game
const distCards = () => ({
type: "DIST_CARDS",
payload: (state) => {
const cards = [...state.cards];
shuffle(cards);
const computer_cards = cards.slice(0, NUM_OF_CARDS / 2);
const player_cards = cards.slice(NUM_OF_CARDS / 2);
const computer_current_card = computer_cards.pop();
const player_current_card = player_cards.pop();
return {
...state,
cards,
// distributes cards evenly
computer: {
...state.computer,
cards: computer_cards,
current_card: computer_current_card,
points: 0,
},
player: {
...state.player,
cards: player_cards,
current_card: player_current_card,
points: 0,
},
};
},
});
const setNextCards = () => ({
type: "SET_NEXT_CARDS",
payload: (state) => {
let [computer_cards, player_cards] = [
[...state.computer.cards],
[...state.player.cards],
];
const [computer_next_card, player_next_card] = [
computer_cards.pop(),
player_cards.pop(),
];
return {
...state,
player: {
...state.player,
cards: player_cards,
current_card: player_next_card,
},
computer: {
...state.computer,
cards: computer_cards,
current_card: computer_next_card,
},
};
},
});
const pointsIncreament = () => ({
type: "INCREASE_POINTS",
payload: (state) => {
const [player_current_card, computer_current_card] = [
state.player.current_card,
state.computer.current_card,
];
return {
...state,
player: {
...state.player,
points:
player_current_card > computer_current_card
? state.player.points + 1
: state.player.points,
},
computer: {
...state.computer,
points:
player_current_card < computer_current_card
? state.computer.points + 1
: state.computer.points,
},
};
},
});
function Game() {
const player = useSelector(({ player }) => player);
const computer = useSelector(({ computer }) => computer);
const game_ready = useSelector(({ game_ready }) => game_ready);
const dispatch = useDispatch();
const history = useHistory();
const handleReset = React.useCallback(() => {
dispatch(distCards());
}, [dispatch]);
useEffect(() => {
if (game_ready) {
dispatch(distCards());
} else {
history.replace("/");
}
}, [game_ready]);
useEffect(() => {
if (player.current_card && computer.current_card) {
dispatch(pointsIncreament());
}
}, [player.current_card, computer.current_card]);
const handleClick = React.useCallback(() => {
dispatch(setNextCards());
});
return (
<div className="flex justify-center">
<div className="flex flex-col">
<div>
<div>{player.name}</div>
<div>Points: {player.points}</div>
<div>{player.current_card}</div>
</div>
<div>
<div>{computer.current_card}</div>
<div>Points: {computer.points}</div>
<div>{computer.name}</div>
</div>
{!player.cards.length || !computer.cards.length ? (
<Button
onClick={handleReset}
type="submit"
color="primary"
variant="contained"
>
Again?
</Button>
) : (
<Button
onClick={handleClick}
type="submit"
color="primary"
variant="contained"
>
next
</Button>
)}
<div>
{!player.cards.length || !computer.cards.length ? (
player.points === computer.points ? (
<h2>It's a tie</h2>
) : player.points > computer.points ? (
<h2>{player.name} won!</h2>
) : (
<h2>{computer.name} won!</h2>
)
) : (
""
)}
</div>
</div>
</div>
);
}
export default Game;

How to add a class to an image by click?

How to add a class to an image if the flag is done: true? As I have not tried, the class is added to all images, and not to those with true...
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [avatarArr, setAvatarArr] = useState({
avatar: [
{
id: 1,
url: "https://starwars-visualguide.com/assets/img/characters/1.jpg"
},
{
id: 2,
url: "https://starwars-visualguide.com/assets/img/characters/2.jpg"
},
{
id: 3,
url: "https://starwars-visualguide.com/assets/img/characters/3.jpg"
}
]
});
const [classUser, setClassUser] = useState(null);
const [selectUser, setSelectUser] = useState(false);
const onAddClass = id => {
if (avatarArr.avatar.find(items => items.id === id)) {
const index = avatarArr.avatar.findIndex(items => items.id === id);
setAvatarArr([
...avatarArr.slice(0, index),
...avatarArr.slice(index + 1)
]);
} else {
setAvatarArr([...avatarArr, { done: true }]);
setSelectUser(avatarArr.avatar.map(items => items.done));
if (selectUser) {
setClassUser("active__user");
}
}
};
const blockCreate = () => {
return avatarArr.avatar.map(items => {
return (
<div key={items.id}>
<img
src={items.url}
alt="avatar"
width="150px"
onClick={() => onAddClass(items.done, items.id)}
className={selectUser ? classUser : null}
/>
</div>
);
});
};
return (
<div className="App">
<div>{blockCreate()}</div>
</div>
);
}
<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>
I'm trying to set true on click, to tell the user that the avatar that was clicked on is selected, and add some kind of styling class.
And if you click a second time, then true - becomes false, in short - the choice
Are you looking like this
export default function App() {
const [avatarArr, setAvatarArr] = useState({
avatar: [
{
id: 1,
url: "https://starwars-visualguide.com/assets/img/characters/1.jpg"
},
{
id: 2,
url: "https://starwars-visualguide.com/assets/img/characters/2.jpg"
},
{
id: 3,
url: "https://starwars-visualguide.com/assets/img/characters/3.jpg"
}
]
});
const [selectUser, setSelectUser] = useState(false);
const onAddClass = item => {
setSelectUser(item);
};
const blockCreate = () => {
return avatarArr.avatar.map(items => {
return (
<div key={items.id}>
<img
src={items.url}
alt="avatar"
width="150px"
onClick={() => onAddClass(items)}
className={selectUser.id === items.id ? "myClass" : ""}
/>
</div>
);
});
};
return (
<div className="App">
<div>{blockCreate()}</div>
</div>
);
}
Live working demo https://codesandbox.io/s/vigilant-almeida-169zj

Resources