Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I use a button to control the audio player mute but it makes the player default mute, I want that only mute when clicking.How to edit it
import React, { useState } from "react";
import ReactAudioPlayer from "react-audio-player";
const Test = () => {
const [ismute, setOpen] = useState(false);
return (
<><div>
<ReactAudioPlayer
controls
muted={ismute ? "false": "True"}
src='https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'
loop
autoPlay
/>
</div><button onClick={() => setOpen(!ismute)}>click me!</button>
</>
);
};
export default Test
If you are passing as string,
muted={ismute ? "false": "True"}
since the initial value of the ismute is false as:
const [ismute, setMute] = useState(false);
then what you are going to pass as a prop is True or false which is truthy value which makes ismute as always mute
For state ismute, initially assign value true instead of false as below:
const [ismute, setOpen] = useState(true);
You should pass muted prop as either true or false. You are passing as a string
muted={ismute ? false: true }
I've created a simulation for player
For state ismute, initially assign value true instead of false as below:
const [ismute, setOpen] = useState(true);
Another correction might be at component ReactAudioPlayer:
<ReactAudioPlayer
controls
muted={ismute}
src='https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'
loop
autoPlay
/>
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 days ago.
Improve this question
I'm trying to find the best way to create and update items in a list. So, I have a form with item fields and I have the idea to provide a function (update or create) depending on the mode I choose. For example, I click the edit button and set the "update" mode, or I click the "add new item" button and set the "create" mode. In this case I don't need to add two identical components with different click handlers (one for update, one for create), I will just provide a click handler depending on the mode state.
What do you think about this implementation?
import {useState} from "react";
enum MODES {
view= "view",
update= "update",
create= "create",
}
const Page = () => {
const [mode, setMode] = useState<MODES>(MODES.view);
const [clickHandler, setClickHandler] = useState<() => void>();
const [item, setItem] = useState({});
const updateHandler = () => {};
const createHandler = () => {};
const setModeHandler = (mode: MODES) => {
switch (mode) {
case MODES.update: {
setItem(selectedItem);
setClickHandler(updateHandler);
} break;
case MODES.create: {
setItem({});
setClickHandler(createHandler);
} break;
default: {
} break;
}
}
return (
<div>
<div>
<button onClick={() => {setModeHandler(MODES.update)}}>update</button>
<button onClick={() => {setModeHandler(MODES.create)}}>create</button>
</div>
<ItemModal click={clickHandler} item={item} />
</div>
)
}
I attached the draft to better understand my question.
I would be glad to hear your opinion on this matter.
What do you think about this idea?
Is it okay or better to use to components with different handlers?
This question already has answers here:
Console.log() after setState() doesn't return the updated state
(2 answers)
Closed 10 months ago.
Very simple goal. When a checkbox is clicked set the state of itemOne to true initially. Then it should toggle state if clicked again. When itemOneSelected is invoked itemOne is shown as false.
The question: Why is itemOne set to false instead of true when itemOneSelected is invoked?
const [itemOne, setItemOne] = useState(false);
const itemOneSelected = () => {
setItemOne(!itemOne)
console.log(itemOne)
}
<FormControlLabel control={<Checkbox onClick => { itemOneSelected() } } />}
Remember useState is asynchronous so it will not update straight away. To get the console.log value to log your value you should add a useEffect.
useEffect(() => {
console.log(itemOne)
},[itemOne])
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
I have this code which goes and get the data from API,
const getDevices = async () => {
const response = await fetch(`${API_URL}`);
const json = await response.json();
setData(json);
for (let i in json) {
Object.values(json[i].portOn.split(",")).forEach((value) => {
if (value === "G01") {
blinkStatus = "blink_me";
}
}
and also I have this in return which is supposed to change the className:
<div id="portG01" className={blinkStatus}></div>
But it doesn't work. the DIV doesn't get the className. No error at all.
I am trying to read the data from database and then change the className according to the data.
This is what I need as result:
<div id="portG01" className="blinkStatus"></div>
You need to have blinkStatus changing trigger a rerender of the component. To do this, you can use state. So you can do:
import React, { useEffect, useState } from "react";
...
const [blinkStatus, setBlinkStatus] = useState();
// useEffect(() => {}, []) is the equivalent of the old componentDidMount
useEffect(() => {
const value = await ... // get blink status
setBlinkStatus(value);
}, []);
...
return (
<div className={blinkStatus}>
...
</div>
);
// TuneContainer.js
import React, {useState} from 'react'
import './TuneContainer.css'
function TuneContainer(props) {
const[isPlaying, setIsPlaying] = useState(false)
const[isPaused, setIsPaused] = useState(true)
const audio = document.querySelector('audio')
const audioControls = () => {
if(isPaused) {
console.log(isPlaying)
console.log(isPaused)
setIsPlaying(!isPlaying)
setIsPaused(!isPaused)
console.log(isPlaying)
console.log(isPaused)
audio.play()
} else {
setIsPlaying(!isPlaying)
setIsPaused(!isPaused)
audio.pause()
}
}
return (
<>
<div className="tune-container">
<div className="info-class">
<img src={props.imgsrc} className="tune-img" alt={props.imgalt} onClick={audioControls}></img>
<audio src={props.audiosrc} id="tune" loop hidden></audio>
</div>
</div>
</>
)
}
export default TuneContainer
The above is the code for the container which consist of the image, which when clicked plays the song in an infinite loop, until paused again by clicking the image. Below given is the main page which is calling the TuneContainer and passing it props.
// HomePage.js
import React from 'react'
import NavigationBar from './NavigationBar'
import TuneContainer from './TuneContainer'
import Bird from '../images/Bird.svg'
import BirdWhistling from '../audios/Bird-whistling.mp3'
import Leaves from '../images/Leaves.svg'
import LeavesRustling from '../audios/Rustling-leaves.mp3'
function HomePage() {
return (
<>
<NavigationBar />
<div className="container">
<TuneContainer audiosrc={BirdWhistling} imgsrc={Bird} imgalt="Bird by Ana MarĂa Lora Macias from the Noun Project"/>
<TuneContainer audiosrc={LeavesRustling} imgsrc={Leaves} imgalt="leaves by KP Arts from the Noun Project"/>
</div>
</>
)
}
export default HomePage
So here, when I click on the bird image, I hear the the chirping sounds, since those are the props passed. The second TuneContainer has different image and audio altogether. However, when the leaf image is clicked, it still plays the chirping sound. So I believe the audio source is not properly getting updated. Can someone please highlight where am I doing a mistake?
P.S: Before someone asks, I have checked all the routes and filenames correctly, and no, both audio files have different songs in them.
Although I know the SO highly recommends asking one question in one post, I will just add my second question here, since it is highly related and requires no extra bit of code.
Q: When I check the console, the values getting printed (because of the console.log statements) are false, true, false, true. I believe it should print false, true, true, false, since I am printing once before the setState function and once after it. Why such behaviour?
Because document.querySelector('audio') will always return the first html audio element, which in your case is the bird chirping sound.
You can use a unique (id)entifier for each TuneContainer. Use that id on your audio tag and query select that id, which will point the correct audio element.
Another way would be to use a useRef to get the audio element.
// TuneContainer.js
...
const audioRef = React.useRef(null);
/* const audio = document.querySelector('audio') */
const audioControls = () => {
if(isPaused) {
console.log(isPlaying)
console.log(isPaused)
setIsPlaying(!isPlaying)
setIsPaused(!isPaused)
console.log(isPlaying)
console.log(isPaused)
// audio.play()
audioRef.current.play();
} else {
setIsPlaying(!isPlaying)
setIsPaused(!isPaused)
// audio.pause()
audioRef.current.pause();
}
};
...
...
return (
...
...
<audio ref={audioRef} src={props.audiosrc} id="tune" loop hidden></audio>
...
);
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
What is the correct way to change checkbox value?
option 1
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [x, setX] = useState(false);
const soldCheckbox = ({ target: { checked } }) => {
console.log(x, checked);
setX(checked);
};
return (
<div>
<input type="checkbox" checked={x} onChange={soldCheckbox} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
option 2
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [x, setX] = useState(false);
console.log(x);
return (
<div>
<input type="checkbox" checked={x} onChange={() => setX(!x)} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
In fact, I think there's no difference, but I just wanted to hear a different opinion. Maybe something I do not know or there may be other solutions to this problem.
Both ways are almost the same, but the first option actually is more redundant, let's analyze why:
Both the first and second methods are implementing controlled components
This means that you are providing a value and a way to change it, so the responsibility to update and control the values are abstracted from the component.
But why the first way is redundant?
You don't actually need to read from the e.target.checked cause it always reflects the local state x, so there is no need to read from e.target.checked and reverse it by doing: setX(!e.target.checked) since x and the e.target.checked will always be the same.
Caveats
Even though is fine to do onClick={e => parentHandler(e)} in a inline expression(arrow function) you should be careful, passing it like this to an input won't cause any problems, but when you are passing to a child component that implements React.memo or PureComponent for example, this will actually re render the component everytime, cause a new instance of the function is always created (signature is the same, but the shallow comparison will always return false cause they are different instances), so for optimization reasons is always best pass props like this: <Child onClick={this.clickHandler} id={item.id} /> and on the child: onClick={() => this.props.onClick(this.props.id)} instead of just: <Child onClick={e => this.onClick(item.id)} />
In this specific case, I would have chosen option 2, cleaner code in my opinion.
setX changes the state, no need for a function calling setX and extracting the value from event if we know the value is x.
I think that it all depends on the situation.
The first option will be better if you have a lot of form and components. You can handle all with one handler.
const handler = (e) => {
const { target } = e;
const value = target.type === 'checkbox' ? target.checked : target.value;
const { name } = target;
setForm( f => ({ ...f, [name]: value }));
};
Second, if checkbox is one and the application must somehow react to its change.
there is a third way to uncontrolled inputs.
The only difference is clean coding, first way is better if you need to do something except changing state (for example to call an http request) and the second is good if you just need checkbox to work and store its value.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [x, setX] = useState(false);
const soldCheckbox = ({ target: { checked } }) => {
console.log(x, checked);
setX(checked);
};
return (
<div>
<input type="checkbox" checked={x} onChange={soldCheckbox} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I'm always choosing option 1 because it is a way more generic way for defining form field change events. In most of the cases, I have something in generic form components
function SomeForm() {
const [formData, setFormData] = useState({ name: "", accept: false });
const onFieldChange = ({ target: { name, value, checked } }) => {
if (typeof checked !== 'undefined') { // checking if we have a "checked" field inside target
setFormData({ [name]: checked });
}
setFormData({ [name]: value });
}
return (
<form>
<input type="text" name="name" value={formData.name} onChange={onFieldChange} />
<input type="checkbox" name="accept" checked={formData.accept} onChange={onFieldChange} />
</form>
)
}
The idea behind this is that any way we are going to receive a target DOM object which contains both checked and value, so we can make it generic.
Hope this helps
It looks like both of your options are equivalent. If we look at the documentation for the onChange event provided by React (not the change event provided by html) it states:
The onChange event behaves as you would expect it to: whenever a form field is changed, this event is fired.
We intentionally do not use the existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to handle user input in real time.
DOM Elements
So, simply choose the option that you think produces cleaner code.