How should I implement my Drum Machine App? - javascript

I am creating a drum machine using Reactjs. It is working good but I have some performance issue and I also want to add a audio changing interface. Currently, the app have to initialize an Audio object every time the user clicks a drum pad(too bad!!!) and I tried to add another feature of changing audio but I couldn't.. I am new to Reactjs so any help will be appreciated.
Here is my code:
const App = () => {
return (
<div className="main">
<div className="drumBox">
<h2 className="drumHeader">Drum Machine</h2>
<input type="button" value="Q" onClick={() => play(Q)} />
<input type="button" value="W" onClick={() => play(W)} />
<input type="button" value="E" onClick={() => play(E)} />
<input type="button" value="A" onClick={() => play(A)} />
<br />
<input type="button" value="S" onClick={() => play(S)} />
<input type="button" value="D" onClick={() => play(D)} />
<input type="button" value="Z" onClick={() => play(Z)} />
<input type="button" value="X" onClick={() => play(X)} />
</div>
</div>
);
};
const play = e => {
var snd = new Audio(e);
return snd.play();
};
export default App;
I am calling a play function on clicking each drum pad. As you can see, the audio object snd is initialized on each click. How should I fix this and be able to change volume?

Not sure which JavaScript audio library you are using so I can't test fully this working. Also, I am not sure if you are trying to do it in Angular or not.
However, I can show you how to do it with jQuery assuming that Audio is available.
Change your HTML to:
$(".drum").on('click', function(){
let note = $(this).val();
try{
new Audio(note);
}catch(e){
console.log("Couldn't play note: ".concat(note));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div className="main">
<div className="drumBox">
<h2 className="drumHeader">Drum Machine</h2>
<input class="drum" type="button" value="Q" />
<input class="drum" type="button" value="W" />
<input class="drum" type="button" value="E" />
<input class="drum" type="button" value="A" />
<input class="drum" type="button" value="S" />
<input class="drum" type="button" value="D" />
<input class="drum" type="button" value="Z" />
<input class="drum" type="button" value="X" />
</div>
</div>

maybe by making each pad input a component with is Audio :
const PadInput = ({value})=>{
const a = new Audio(value)
const play = ()=>{
a.play();
}
return (
<input type="button" value={value} onClick={play} />
)
}
and using it like this :
<PadInput value="A"/>
or for only one Audio this can probably work :
class App extends React.Component{
state = {
audio : new Audio()
}
play = (sound)=>{
const {audio} = this.state;
audio.src = sound;
audio.play();
}
render(){
return (
<div className="App">
<PadInput label="A" sound={A} play={this.play}/>
</div>
);
}
}
const PadInput = ({label, sound, play})=>(
<input type="button" value={label} onClick={()=>play(sound)} />
)

Related

How to display multiple object values in alert box using javascript

function myFunction()
{
alert(document.getElementById("myname").value+','+document.getElementById("myphone")+','+document.getElementById("mycountry")+','+document.getElementById("myemail"));
}
it seems pretty straightforward to me
I just refactor a bit your function
function myFunction() {
const message = ['myname', 'myphone', 'mycountry', 'myemail']
.map(id => document.getElementById(id).value)
.join(',')
alert(message);
}
<div>
<input id="myname" placeholder="myname" />
<input id="myphone" placeholder="myphone" />
<input id="mycountry" placeholder="mycountry" />
<input id="myemail" placeholder="myemail" />
</div>
<div>
<button onclick="myFunction()">Show alert</button>
</div>

Strange behavior of inputs during pagination

For some reason, when switching to Registration, the 3rd input "inherits" the value from the previous state, that is, in theory, it should not have a value, but nevertheless an equal Login appears. How to fix?
import React, { useState } from 'react';
function Auth() {
const [pagination, setPagination] = useState('log');
function pag() {
if (pagination === 'log') {
return (
<>
<input
type="text"
className="email"
placeholder="E-mail"
/>
<input
type="text"
className="password"
placeholder="Пароль"
/>
<input
type="button"
className="done"
value="Войти"
/> // From here is transmitted
</>
);
}
return (
<>
<input
type="text"
className="email"
placeholder="E-mail"
/>
<input
type="text"
className="password"
placeholder="Пароль"
/>
<input
type="text"
className="password password-repeat"
placeholder="Повторите пароль"
/> // To here
<input
type="button"
className="done"
value="Зарегестрироваться"
/>
</>
);
}
function changePag(ev) {
if (ev.target.dataset.type === 'log') {
setPagination('log');
} else {
setPagination('reg');
}
}
return (
<div className="auth_page">
<div className="pagination">
<input
type="button"
className="log"
data-type="log"
onClick={changePag}
value="Вход"
/>
<input
type="button"
className="reg"
data-type="reg"
onClick={changePag}
value="Регистрация"
/>
</div>
<div className="form">
{pag()}
</div>
</div>
);
}
export default Auth;

Trying to open modal on button click

I am trying to open ANTD modal when i click on button on the form using the below code
This is HTML code:
<div>
<Button type="primary" size={buttonsize.size} onClick={createproject1}>
Add New Project
</Button>
<div>
<div>
<Modal
title="Add New project"
visible={setvisible.visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Input size="small" placeholder="Project Name" onChange={handleChange('projectName')} />
<br />
<br />
<Input size="small" placeholder="Project Number" onChange={handleChange('projectNumber')} />
<br />
<br />
<Input size="small" placeholder="Area" onChange={handleChange('area')} />
<br />
<br />
</Modal>
</div>
This is the hook and other state stuff:
const [visible, setvisible] = useState({ visible: false });
const createproject1 = (e) => {
setvisible.visible = true;
};
I am not sure where i am going in wrong direction.. could any one please let me know is there any way to open a modal that would be very grateful to me
From the docs:
Returns a stateful value, and a function to update it.
setvisible is a function, which allows you to update the state. You would need to call it like so:
setvisible({visible: true});
Since this is as simple as a bool, and object isn't necessary here:
const [visible, setVisible] = useState(false)
Then you could simply call:
setVisible(true);
Since you're still having issues, let me make this dirt simple for you:
const [visible, setVisible] = useState(false)
And your component:
<div>
<Button type="primary" size={buttonsize.size} onClick={() => setVisible(true)}>
Add New Project
</Button>
<div>
<div>
<Modal
title="Add New project"
visible={visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Input size="small" placeholder="Project Name" onChange={handleChange('projectName')} />
<br />
<br />
<Input size="small" placeholder="Project Number" onChange={handleChange('projectNumber')} />
<br />
<br />
<Input size="small" placeholder="Area" onChange={handleChange('area')} />
<br />
<br />
</Modal>
</div>
For creating hooks as single value variable, you don't have to create hooks like this..
const [visible, setvisible] = useState({ visible: false });
Instead use this...
const [visible, setvisible] = useState(false);
Here setVisible is Hooks function not an object..
So you cannot set visible value by setVisible.visible = true.
Rather you should have you write this :
setVisible(true)
and Use visible variable as visible attribute of modal .
<Modal
...
visible={visible}
...
>

How can I append objects to the body of a component in React?

I am trying to set up some functionality on this React component so that a user can add and remove empty radio button options to a page that a user can type text into. The only issue that I am having is that I am relatively new to React and am not 100% how to do this.
import React, { Component } from 'react';
class TextRadio extends Component {
constructor() {
super();
state = {
textValue: ""
}
};
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
}
addBox = () => {
}
removeBox = () => {
}
render() {
return(
<div>
<div className="form-check">
<input className="form-check-input" type="radio" id="" name="" value="" />
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
The result that I am expecting to happen is to have it so the component can add and remove radio button options from the page depending on the button that the user presses
i was completed just your addBox and RemoveBox functions, i hope that's help you
import React, { Component } from "react";
class TextRadio extends Component {
constructor() {
super();
this.state = {
radioButtons: []
};
}
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
};
addBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length === 0) {
radioButtons.push({
id: 1,
name: "radiobutton",
value: "test"
});
return {
radioButtons: radioButtons
};
} else {
radioButtons.push({
id: radioButtons[radioButtons.length - 1].id + 1,
name: "raiodButton_" + (radioButtons[radioButtons.length - 1].id + 1),
value: radioButtons[radioButtons.length - 1].value
});
return {
radioButtons: radioButtons
};
}
});
};
removeBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length !== 0) {
radioButtons.pop(radioButtons[radioButtons.length - 1]);
return {
radioButtons: radioButtons
};
} else {
return { radioButtons: radioButtons };
}
});
};
render() {
return (
<div>
<div className="form-check">
{this.state.radioButtons.map(radiobutton => {
return (
<div>
<input
className="form-check-input"
type="radio"
id={radiobutton.id}
name={radiobutton.name}
value={radiobutton.value}
/>
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
);
})}
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button
type="button"
className="btn btn-danger"
onClick={this.removeBox}
>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
https://codesandbox.io/embed/confident-browser-tmojp
I was playing around with your idea and made some changes in the code, just to show you an example, how you can dynamically create new components and store them in applications state and then render out to user based on their actions.
I created new component just for form UI: option, input field and remove button. If user clicks on the Add Option, new item of the component is added to application state and then render out. Remove button is used to remove Item from state.
class TextRadio extends Component {
state = {
optionInputs: []
};
addBox = () => {
const optionInputsUpdated = [
...this.state.optionInputs,
<OptionInput id={uuid.v4()} remove={this.removeBox} />
];
this.setState({ optionInputs: optionInputsUpdated });
};
removeBox = id => {
const optionInputsUpdated = this.state.optionInputs.filter(
item => item.props.id !== id
);
this.setState({ optionInputs: optionInputsUpdated });
};
render() {
return (
<div>
{this.state.optionInputs.map((optionInput, idx) => {
return (
<div key={idx} test="123">
{optionInput}
</div>
);
})}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
</div>
);
}
}
const OptionInput = props => {
return (
<div className="form-check">
<input
className="form-check-input"
type="radio"
id=""
name="radio"
value=""
/>
<label className="form-check-label" for="">
<input className="form-control" type="text" placeholder="" />
</label>{" "}
<button
type="button"
className="btn btn-danger"
onClick={() => props.remove(props.id)}
>
Remove Option
</button>
</div>
);
};
Hope this gives you better understanding, how to achieve your goal.
If you need additional help, just post a comment under this answer, and I will update demo to help you.
Here is DEMO I created from your code: https://codesandbox.io/s/nice-ganguly-s4wls
first you have to initialize an empty array state
this.state={
radioButtons : [{input:''}]
}
then in your return statement you have to loop through the radioButtons array and show the radio button with input
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
then in your addBox function append an object on every click
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
function to remove a radio button object
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
Final code Looks like this :
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component{
constructor(props){
super(props);
this.state={
radioButtons :[{input:''}]
}
}
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
render(){
return(
<div>
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
codepen Example

How can i create input text fields dynamically in react js - JSX?

I'm pretty new to reactjs, i came across a scenario where i've to create 6 input fields which are very much similar to each other. Right now i've something like this in my render method of class,
render () {
return (
<div>
<p>
<label htmlFor="answer1">Answer:</label><br/>
<input
type="text"
name="answer1"
id="answer1"
className="answer"
value={this.state.answer1}
onChange={this._handleChange}
/>
</p>
<p>
<input
type="text"
name="answer2"
id="answer2"
className="answer"
value={this.state.answer2}
onChange={this._handleChange}
/>
</p>
<p>
<input
type="text"
name="answer3"
id="answer3"
className="answer"
value={this.state.answer3}
onChange={this._handleChange}
/>
</p>
<p>
<input
type="text"
name="answer4"
id="answer4"
className="answer"
value={this.state.answer4}
onChange={this._handleChange}
/>
</p>
<p>
<input
type="text"
name="answer5"
id="answer5"
className="answer"
value={this.state.answer5}
onChange={this._handleChange}
/>
</p>
<p>
<input
type="text"
name="answer6"
id="answer6"
className="answer"
value={this.state.answer6}
onChange={this._handleChange}
/>
</p>
</div>
);
}
The code is ugly and redundant, is there anyway i could do this dynamically?
How about defining an Answer component like this (only showing the render method):
render() {
return (
<p>
<label htmlFor={this.props.name}>Answer:</label>
<input
type="text"
name={this.props.name}
className="answer"
value={this.props.value}
onChange={this.props.handleChange}
/>
</p>
);
}
And then on your parent component you just import it and use it like:
var Answer = require('./answer.js');
//..
render() {
return (
<div>
<Answer name="answer1" value={this.state.answer1} handleChange={this._handleChange} />
<Answer name="answer2" value={this.state.answer2} handleChange={this._handleChange} />
<Answer name="answer3" value={this.state.answer3} handleChange={this._handleChange} />
// add all your Answer components
</div>
);
}
Following Thylossus suggestion, here is an example using map:
var Answer = require('./answer.js');
//...
render() {
// this is supposing you've got an answers array of { name: ..., value: ...} object
var answers = this.state.answers.map(function(a) {
return(<Answer name={a.name} value={a.value} handleChange={this._handleChange} />)
});
return (
<div>
{ answers }
</div>
);
}

Categories