I was getting this error when I want to play an audio in my website, I tried some things that I found in others questions, but it doesn't work to me. This is the code:
import { useEffect, useRef, useState } from "react";
import MusicPlayer from "../Molecules/MusicPlayer";
import { songList } from "../../tools/songList";
function NavBar(props) {
const [songs, setSongs] = useState([]);
const [isPlaying, setIsPlaying] = useState(false);
const [songOn, setSongOn] = useState(0);
let songPlayer = useRef(null);
useEffect(() => {
setSongs(songList);
}, []);
let pickSong = (index) => {
songPlayer.current.src = songs[index].audio;
};
let playSong = () => {
songPlayer.current.load();
songPlayer.current
.play()
.then((_) => {})
.catch((err) => {
console.info(err);
});
};
let pauseSong = () => {
songPlayer.current.pause();
};
return (
<>
<div className="nav-bar">
<MusicPlayer
songs={songs}
playSong={playSong}
currentSong={songPlayer}
pauseSong={pauseSong}
isPlaying={isPlaying}
setIsPlaying={setIsPlaying}
pickSong={pickSong}
setSongOn={setSongOn}
songOn={songOn}
/>
</div>
<audio
src={songs[0] !== null && songs[0] !== undefined ? songs[0].audio : ""}
ref={songPlayer}
></audio>
</>
);
}
export default NavBar;
import React from "react";
import "./MusicPlayer.css";
function MusicPlayer(props) {
const prevSong = () => {
if (props.songs[props.songOn - 1] !== undefined) {
props.pickSong(props.songOn - 1);
props.playStop();
props.setSongOn(props.songOn - 1);
props.setIsPlaying(true);
} else if (props.songs[props.songOn - 1] === undefined) {
props.pickSong(props.songs.length - 1);
props.playStop();
props.setSongOn(props.songs.length - 1);
props.setIsPlaying(true);
}
};
const nextSong = () => {
if (props.songs[props.songOn + 1] !== undefined) {
props.pickSong(props.songOn + 1);
props.playSong();
props.setSongOn(props.songOn + 1);
} else if (props.songs[props.songOn + 1] === undefined) {
props.pickSong(0);
props.playSong();
props.setSongOn(0);
}
};
const playPause = () => {
if (props.currentSong.current.paused) {
props.playSong();
props.setIsPlaying(true);
} else {
props.pauseSong();
props.setIsPlaying(false);
}
};
return (
<div className="player">
<div className="main">
<div className="controls">
<div className="prev-control" onClick={() => prevSong()}>
<i className="fas fa-step-backward"></i>
</div>
<div
className="play-pause-control paused"
onClick={() => playPause()}
>
<i className="fas fa-play"></i>
<i className="fas fa-pause"></i>
</div>
<div className="next-control" onClick={() => nextSong()}>
<i className="fas fa-step-forward"></i>
</div>
</div>
<div className="details">
<p></p>
</div>
<div className="seekbar">
<input type="range" />
</div>
</div>
</div>
);
}
export default MusicPlayer;
Is there a way to play the audio using the react refs? Or would I have to change it? If you want more info you can let me know in the comments
Related
I am trying to complete my first React project by myself but I am having some problems. I am mapping a JSON file with each having an input field to add item amount to the cart. The problem is when I change one input value, all the input values change. I want them to change independently. I am trying to use id in this case but I don't know the proper way to put that in the code.
import React, { useState } from "react";
import "./produce.css";
import produce from "../produce.json";
import { MdArrowDropUp, MdArrowDropDown } from "react-icons/md";
const Produce = () => {
const [amount, setAmount] = useState(0);
const handleIncrease = () => {
if (amount < 20) {
setAmount(Number(amount) + 1);
}
};
const handleDecrease = () => {
if (amount > 0) {
setAmount(Number(amount) - 1);
}
};
const handleChange = (e, id) => {
setAmount(e.target.value)
};
return (
<div className="produce">
{produce.map((item) => {
return (
<div className="produce_item" key={item.id}>
<img className="item_img" src={item.img} />
<div className="produce_explain">
<div className="produce_explain1">
<h3>{item.name}</h3>
{item.iconOrganic && <img src={item.iconOrganic} />}
</div>
<div className="produce_explain2">
{item.organic === "organic" && <h5>{item.organic}</h5>}
<div className="produce_weight">
<h6>approx.</h6>
{item.weight}
</div>
</div>
<div className="produce_price">
<h3>{item.price} $</h3>
</div>
</div>
<div className="produce_buy">
<button className="produce_cart">Add to Cart</button>
<div className="produce_number">
<button className="produce_increase" onClick={handleIncrease}>
<MdArrowDropUp />
</button>
<input
type="text"
className="produce_count"
value={amount}
onChange={(e) => handleChange(e, item.id)}
/>
<button className="produce_decrease" onClick={handleDecrease}>
<MdArrowDropDown />
</button>
</div>
</div>
</div>
);
})}
</div>
);
};
export default Produce;
Save the amount in the produce list itself. As you are looping through produce to show the value.
import React, { useState } from "react";
import "./produce.css";
import produceListData from "../produce.json";
import { MdArrowDropUp, MdArrowDropDown } from "react-icons/md";
const Produce = () => {
const [produceList, setProduceList] = useState(produceListData.map(produce => { return {...produce, amount: 0}}));
const handleIncrease = (id) => {
if (amount < 20) {
const newList = produceList.map((item) => {
if (item.id === id) {
const updatedItem = {
...item,
amount: item.amount ? Number(item.amount) + 1 : 1,
};
return updatedItem;
}
return item;
});
setProduceList(newList);
}
};
const handleDecrease = () => {
if (amount > 0) {
const newList = produceList.map((item) => {
if (item.id === id) {
const updatedItem = {
...item,
amount: item.amount ? Number(item.amount) - 1 : 0,
};
return updatedItem;
}
return item;
});
setProduceList(newList);
}
};
const handleChange = (e, id) => {
const newList = produceList.map((item) => {
if (item.id === id) {
const updatedItem = {
...item,
amount: item.amount ? Number(item.amount) - 1 : 0,
};
return updatedItem;
}
return item;
});
setProduceList(newList);
};
const updateAmount = (amount, id) => {
};
return (
<div className="produce">
{produce.map((item) => {
return (
<div className="produce_item" key={item.id}>
<img className="item_img" src={item.img} />
<div className="produce_explain">
<div className="produce_explain1">
<h3>{item.name}</h3>
{item.iconOrganic && <img src={item.iconOrganic} />}
</div>
<div className="produce_explain2">
{item.organic === "organic" && <h5>{item.organic}</h5>}
<div className="produce_weight">
<h6>approx.</h6>
{item.weight}
</div>
</div>
<div className="produce_price">
<h3>{item.price} $</h3>
</div>
</div>
<div className="produce_buy">
<button className="produce_cart">Add to Cart</button>
<div className="produce_number">
<button className="produce_increase" onClick={(e) => handleIncrease(item.id)}>
<MdArrowDropUp />
</button>
<input
type="text"
className="produce_count"
value={amount}
onChange={(e) => handleChange(e, item.id)}
/>
<button className="produce_decrease" onClick={(e) => handleDecrease(item.id)}>
<MdArrowDropDown />
</button>
</div>
</div>
</div>
);
})}
</div>
);
};
export default Produce;
i don't know how can i print user info react modal
this is my code
import React from "react";
import axios from "axios";
import { useEffect, useState } from "react";
import { Show, User } from "../api";
import UseUser from "../scroll/userInfo";
function ShowContents() {
const [storyIds, setStoryIds] = useState([]);
const [visible, setVisible] = useState(false);
const [getUser, setGetUser] = useState([]);
useEffect(() => {
Show().then((res) => {
this.res = res.data.slice(0, 10);
this.res.forEach(async (ele) => {
await axios
.get("https://hacker-news.firebaseio.com/v0/item/" + ele + ".json")
.then((res) => {
if (Array.isArray(this.res) && this.res.length === 0) {
return;
} else {
setStoryIds((value) => [
...value,
{
id: res.data.id,
title: res.data.title,
url: res.data.url,
user: res.data.by,
score: res.data.score
}
]);
}
});
});
});
}, []);
const menu = storyIds;
const menuList = menu.map((m, i) => (
<div className="box_show" key={i}>
<div className="flex">
<p className="numbers">{i + 1}</p>
<a href={m.url} className="titleFont">
{m.title}
</a>
<a href={m.url}>
<img src={`/assets/back.svg`} alt="" className="imgLink" />
</a>
</div>
<br />
<button
className="userShow"
onClick={() => {
setVisible(!visible);
}}
>
<div className="userNameShow">{m.user}</div>
</button>
</div>
));
return (
<>
{menuList}
{visible && (
<div className="modal-container" id="modal">
<div className="modal">
<div className="modal-top flex">
<p>User Info</p>
<button
className="close-btn"
onClick={() => {
setVisible(!visible);
}}
>
<img src={`/assets/close_black.svg`} alt="" />
</button>
</div>
<UseUser />
</div>
</div>
)}
</>
);
}
export default ShowContents;
The code above is my show partial code.
this is my UserInfo code
import { useState, useEffect } from "react";
import { getUser } from "../api";
const UseUser = (id) => {
// const [user, setUser] = useState({});
// useEffect(() => {
// getUser(id).then((user) => setUser(user));
// }, [id]);
return (
<>
<div className="user-detail flex">
<div className="user-profile"></div>
<div className="user-detail-info">
<p className="modal-user">user : </p>
<p className="modal-created">created : </p>
<p className="modal-karma">karma : </p>
</div>
</div>
<p className="about">about:</p>
<p className="email">Twitter:</p>);
</>
);
};
export default UseUser;
import axios from "axios";
const BASE_URL = "https://hacker-news.firebaseio.com/v0/";
export const storyUrl = `${BASE_URL}item/`;
function News() {
return axios.get(`${BASE_URL}newstories.json`);
}
function Jobs() {
return axios.get(`${BASE_URL}jobstories.json`);
}
function Top_API() {
return axios.get(`${BASE_URL}topstories.json`);
}
function Ask() {
return axios.get(`${BASE_URL}askstories.json`);
}
function Show() {
return axios.get(`${BASE_URL}showstories.json`);
}
function User() {
return axios.get(`${BASE_URL}user`);
}
export { News, Jobs, Top_API, Ask, Show, BASE_URL, User };
this is my api code
When you click the user button in the show part, I want to get information about the user. It's too difficult for me right now.
I tried to implement it using use Effect, but I don't know how to send information about the user when I press the button.
I need help.
I am creating a page to update product details on an e-commerce site I am building using NextJS, and I have the image upload section nested inside an accordion on the individual item page. Once images have been uploaded, I would like to clear the upload form and close the accordion. It is closing the accordion I am having trouble with.
ImageUploadAccordion.js:
import React, {useRef} from 'react';
import {Accordion} from 'react-bootstrap'
import ImageUpload from './ImageUpload'
export default function ImageUploadAccordion({ item }) {
const accordionRef = useRef(null);
const toggleAccordion = () => {
accordionRef.current.click();
}
return (
<Accordion ref={accordionRef} defaultActiveKey="0">
<Accordion.Item eventKey="1">
<Accordion.Header>
<span className="btn btn-outline-success">Upload Images</span>
</Accordion.Header>
<Accordion.Body>
<ImageUpload
toggle={toggleAccordion}
item={item}
/>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
ImageUpload.js:
import React, {useState} from 'react';
import { useRouter } from 'next/router'
export default function ImageUpload({ item, toggle }) {
const router = useRouter()
const [images, setImages] = useState([])
const [imageURLS, setImageURLS] = useState([])
const [tags, setTags] = useState([])
const [theInputKey, setTheInputKey] = useState('')
const uploadImageToClient = (event) => {
if (event.target.files && event.target.files[0]) {
setImages((imageList) => [...imageList, {"index": images.length, "data": event.target.files[0]}]);
setImageURLS((urlList) => [
...urlList,
URL.createObjectURL(event.target.files[0])
]);
}
let randomString = Math.random().toString(36);
setTheInputKey(randomString)
};
const uploadTagToClient = (e) => {
if (event.target.value) {
const name = e.target.getAttribute("name")
// const i = event.target.value;
// document.getElementById("image-upload")
setTags((tagList) => [...tagList, {"name": name, "tag": e.target.value}]);
}
};
const removeImage = (name) => {
// debug
alert(`Trying to remove image index ${name}`)
let newImages = []
let newTags = []
setImages(images.filter(image => image.data.name !== name));
setTags(tags.filter(tag => tag.name !== name));
}
const uploadToServer = async (e) => {
const body = new FormData()
images.map((file, index) => {
body.append(`file${index}`, file.data);
});
// Use the filenames as keys then we can retrieve server side once we have the images
tags.map((tag, index) => {
body.append(tag.name, tag.tag)
})
const response = await fetch("/api/file", {
method: "POST",
"Content-Type": "multipart/form-data",
body
})
var message = await response.json();
alert(message['message'])
setImages([])
setTags([])
toggle()
};
const openImageUploadDialogue = () =>{
document.getElementById("image-upload").click()
}
return (
<div className="container">
<input style={{display:'none'}} accept="image/*" id="image-upload" type="file" key={theInputKey || '' } className="btn btn-outline-success-inverse" onChange={uploadImageToClient} />
<button className="btn btn-outline-success-inverse" onClick={openImageUploadDialogue} >
Add Image
</button>
<hr className = "text-pink"/>
<div className="row">
<div className="col d-flex flex-wrap">
{images.map((file, index) => {
return (
<div className="div p-1" key={file.data.name}>
<p className="text-pink">{file.data.name}</p>
<p>Tag</p>
<input type="text" name={file.data.name} id={`${file.data.name}`} onChange={uploadTagToClient} />
<img src={imageURLS[index]} height="200" width="150" />
<div className="btn btn-outline-success-inverse" onClick={ () =>removeImage(file.data.name)}>Remove Image</div>
</div>
);
})}
</div>
<button
className="btn btn-outline-success-inverse"
type="submit"
onClick={uploadToServer}
>
Upload Images
</button>
</div>
</div>
);
}
I tried by creating a reference to the accordion using useRef, and a function which uses this reference to activate the click event, which I passed to the ImageUpload component, according to another answer to a similar question, but it doesn't seem to work and I'm unsure as to why.
Any help always appreciated :-)
I believe you have the wrong target as the ref, update it to target the button that is automatically generated to wrap the header content.
<h2 class="accordion-header"><button type="button" aria-expanded="true" class="accordion-button"><span class="btn btn-outline-success">Upload Images</span></button></h2>
Rudimentary example:
export default function ImageUploadAccordion({ item }) {
const accordionRef = useRef(null);
const toggleAccordion = () => {
accordionRef.current.querySelector('button').click();
}
return (
<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="1">
<Accordion.Header ref={accordionRef}>
<span className="btn btn-outline-success">Upload Images</span>
</Accordion.Header>
<Accordion.Body>
<ImageUpload
toggle={toggleAccordion}
item={item}
/>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
I am developing a web application using MERN stack. I have implemented pagination using React & Bootstrap.
WHAT DO I WANT?
Currently, I have a limited data set. So, the number of pages shown in the pagination are manageable. But with a larger data set, I should be able to limit the number of pages shown in the pagination. The result I am looking for is the pagination implemented at the site www.flanker.net.
The following are my code snippets.
components/Movies.js
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import MoviesTable from "./MoviesTable";
import { fetchMovies } from "./moviesSlice";
import "./Movies.css";
import Pagination from "./common/Pagination";
import { paginate } from "./../utils/paginate";
const Movies = () => {
const [pageSize, setPageSize] = useState(4);
const [currentPage, setCurrentPage] = useState(1);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchMovies());
}, [dispatch]);
const handlePageChange = (page) => {
setCurrentPage(page);
};
const handlePreviousClick = () => {
setCurrentPage(currentPage - 1);
};
const handleNextClick = () => {
setCurrentPage(currentPage + 1);
};
const { status, movies } = useSelector((state) => state.movies);
const paginatedMovies = paginate(movies, currentPage, pageSize);
let content;
if (status === "loading") {
content = (
<div className="spinner">
<div className="spinner-border text-success">
<span class="sr-only">Loading...</span>
</div>
</div>
);
} else {
content = (
<div className="row">
<div className="col-xs-10 col-md-8 mx-auto mt-3">
{paginatedMovies.length > 0 ? (
<MoviesTable movies={paginatedMovies} />
) : null}
<Pagination
itemsCount={movies.length}
pageSize={pageSize}
currentPage={currentPage}
onPageChange={handlePageChange}
onPreviousClick={handlePreviousClick}
onNextClick={handleNextClick}
/>
</div>
</div>
);
}
return <>{content}</>;
};
export default Movies;
components/pagination.js
import React from "react";
import _ from "lodash";
const Pagination = ({
itemsCount,
pageSize,
onPageChange,
currentPage,
onPreviousClick,
onNextClick,
}) => {
const pageCount = Math.ceil(itemsCount / pageSize);
if (pageCount === 1) return null;
const pages = _.range(1, pageCount + 1);
return (
<nav aria-label="Page navigation example">
<ul className="pagination">
{currentPage !== 1 && (
<li class="page-item">
<a
className="page-link"
style={{ cursor: "pointer" }}
onClick={onPreviousClick}
>
Previous
</a>
</li>
)}
{pages.map((page) => (
<li
key={page}
className={page === currentPage ? "page-item active" : "page-item"}
>
<a
style={{ cursor: "pointer" }}
className="page-link"
onClick={() => onPageChange(page)}
>
{page}
</a>
</li>
))}
{currentPage !== pageCount && (
<li class="page-item">
<a
className="page-link"
style={{ cursor: "pointer" }}
onClick={onNextClick}
>
Next
</a>
</li>
)}
</ul>
</nav>
);
};
export default Pagination;
src/utils/paginate.js
import _ from "lodash";
export function paginate(items, pageNumber, pageSize) {
const startIndex = (pageNumber - 1) * pageSize;
return _(items).slice(startIndex).take(pageSize).value();
}
I did some research in the internet, but could not find a solution. I don't know where to start. I would appreciate any help.
I had the same problems and I resolved them with this algorithm :
handleClick(event) {
this.TotalPage();
this.setState({
currentPage: Number(event.target.id)
});
}
const pageNumbers = 10;
ShowPaginationNumbers(pageNumbers) {
let paginationNumbers = [];
if (pageNumbers) {
let showMax = 3;
let endPage;
let startPage;
if (pageNumbers <= showMax) {
startPage = 1;
endPage = pageNumbers.length;
}
else {
startPage = this.state.currentPage;
if (startPage != pageNumbers.length && (startPage + 1) != pageNumbers.length) {
endPage = this.state.currentPage + showMax - 1;
}
else {
endPage = pageNumbers.length;
}
}
for (let i = startPage; i <= endPage; i++) {
paginationNumbers.push(i);
}
return this.ShowRenderPageNumbers(paginationNumbers);
}
}
ShowRenderPageNumbers(paginationNumbers) {
if (paginationNumbers) {
let result = paginationNumbers.map(number => {
return (
<li className="page-item" >
<a className={(this.state.currentPage === number ? ' active' : '') + ' page-link'} key={number} id={number} onClick={this.handleClick}>{number}</a>
</li>
);
});
return result;
}
}
Hello I need to setup a progress bar. So when I press on the button progress bar shows, the button and the content inside of it dispears proggress bar starts to go 0 100 and as well shows some text above, and
when it reaches the 100% progress bar disppears and text above, but after that new text shows. Thanks in Advance
import React,{useEffect, useState} from 'react'
import LinearProgress from '#material-ui/core/LinearProgress'
const useStyles = makeStyles({
root: {
width: '100%',
},
});
const Content =(props)=> {
const classes = useStyles();
const[hideContent, setHideContent]= React.useState(false)
const [progress, setProgress] = React.useState(10);
function handleClick12 ()
{setHideEset(true) }
useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 10 : prevProgress + 10));
}, 800);
return () => {
clearInterval(timer);
};
}, []);
return (
{!hideContent &&
<div className='esetNod__info'>
<h3>Hello</h3>
<Button onClick={handleClick12} className='fix__button'variant='outlined'></Button>
<div >
<LinearProgress value={progress} />
</div>
</div>
}
</div>
)
}
export default Content;
I tried to write something for you:
import React, { useState } from "react";
import LinearProgress from "#material-ui/core/LinearProgress";
const Content = () => {
const [isLoading, setIsLoading] = useState(false);
const [hasLoaded, setHasLoaded] = useState(false);
const [progress, setProgress] = useState(0);
const handleClick = () => {
setIsLoading(true);
const interval = setInterval(() => {
setProgress((prevProgress) => {
const next = prevProgress + 10;
if (next === 100) {
clearInterval(interval);
setIsLoading(false);
setHasLoaded(true);
}
return next;
});
}, 800);
};
if (!isLoading && !hasLoaded) {
return (
<div className="esetNod__info">
<h3>Pre load content</h3>
<button onClick={handleClick} className="fix__button">
Load Content
</button>
</div>
);
} else if (isLoading && !hasLoaded) {
return (
<diV>
<h3>Loading content</h3>
<LinearProgress value={progress} />
</diV>
);
} else {
return (
<div>
<h3>Post load content</h3>
</div>
);
}
};
export default Content;