I'm new to React,
just to get the idea, how would you convert this snippet to React?
<div id="input" contenteditable></div>
<button id="submit">Convert to kg!</button>
<br>
<div id="output"></div>
<script>
const button = document.querySelector('#submit');
const input = document.querySelector('#input');
function convert() {
let x=input.textContent;
if (isNaN(x))
{
alert("Must input numbers");
return false;
} else {
const pounds = document.querySelector('#input').textContent;
let kg = pounds*0.45;
document.querySelector('#output').innerHTML = pounds + " pounds is " + kg + " kg";
}
}
button.addEventListener('click', convert);
</script>
I transformed html to jsx
<div
id="input"
contentEditable
style={{ width: "40%", border: "solid 1px black", margin: "20px}" }}
/>
<button id="submit">Convert to kg!</button>
<br />
<div id="output" style={{ marginTop: 20 }} />
</div>
But, how to go about Javascript, no idea...
Can someone give a direction maybe?
Basic functional component:
weightLb state variable to hold user input
weightKg state variable to hold converted weight
component & logic:
function App() {
const [weightLb, setWeightLb] = useState(0);
const [weightKg, setWeightKg] = useState(0);
const convert = () => {
if (Number.isNaN(weightLb)) {
alert("Must input numbers");
}
setWeightKg(weightLb * 0.45);
}
return (
<div className="App">
<label>
Pounds
<input type="number" onChange={e => setWeightLb(e.target.value)} />
</label>
<button type="button" onClick={convert}>Convert to kg!</button>
<div>Weight (kg): {weightKg}</div>
</div>
);
}
Note: I didn't apply any styling other than default in sandbox.
A simpler abstraction may be to forego the button to convert and just convert input onChange on the fly; requires single piece of state.
function App() {
const [weightLb, setWeightLb] = useState(0);
const convert = () => {
if (Number.isNaN(weightLb)) {
alert("Must input numbers");
}
return weightLb * 0.45;
};
return (
<div className="App">
<label>
Pounds
<input type="number" onChange={e => setWeightLb(e.target.value)} />
</label>
<div>Weight (kg): {convert()}</div>
</div>
);
}
Here are the 6 steps for implementing the React component as per the above requirement:
Define a React Component called App, which extends React Component.
Initialize the 'state' of the component in the constructor method of the component.
The state will contain the variables (weightLb, weightKg)
Define a method (setWeightLb) to change the value of weightLb
Define a method (convert) to calculate weightKg using the formula of
kg = lb x 0.453592
Define 'render' method to show static html of thecomponent
Inside the render method, make calls to setWeightLb and convert on corresponding events.
Here is the working example:
import React, { Component } from "react"
export default class App extends Component {
constructor(props) {
super(props)
this.state = {weightLb: 0.0, weightKg: 0.0}
}
setWeightLb = (value) => {
this.setState({weightLb: value})
}
convert = () => {
this.setState({weightKg: (this.state.weightLb * 0.453592)})
}
render() {
return (
<div>
<label>
Pounds
<input type="number" onChange={e => this.setWeightLb(e.target.value)} />
</label>
<button type="button" onClick={this.convert}>
Convert to kg!
</button>
<div>Weight (kg): {this.state.weightKg}</div>
</div>
)
}
}
Something like this. It may not work as you wished but from this example you can easly create your own answer i guess.
import React from "react";
const convert = (text) => {
if (parseInt(text, 10) > 0) {
const kg = parseInt(text, 10) * 0.45;
document.querySelector("#output").innerHTML =
text + " pounds is " + kg + " kg";
}
alert("You must enter digits");
};
const ExampleComponent = () => {
const [text, setText] = React.useState("");
return (
<section>
<div id="input" onChange={(e) => setText(e.target)}></div>
<button id="submit" onClick={() => convert(text)}>
Convert to kg!
</button>
<br />
<div id="output"> </div>
</section>
);
};
Related
I have three inputs.
One is the input of getting html date.
Second is the input that receives the first time in 24-hour format. (ex: HH:00)
And the last is an input that receives mm in 24-hour format. (ex: 23:MM)
For your information, the first input is getting a value called prop.editTodoAnswer.inception.
I have to combine all of these inputs into one and make the following output. "2022-12-01T00:00:00"
How can we express the value according to the format? Next is my code
const inceptionValues = {
date: props.editTodoAnswer.inception,
fristTime: '00',
secondeTime: '00',
}
const [inceptionTest, setInceptionTest] = useState(inceptionValues);
const handleChangeInception = (e: any) => {
const newInception = e.target.value;
setInceptionTest(newInception)
}
--------------------------
<form onChange={e => handleChangeInception(e)}>
<input style={{margin:'0 5px 0 0'}} type="date" name="date" defaultValue={inceptionValues.date}/>
<input style={{border:'none'}} type="number" name="fristTime" min="0" max="23" placeholder="23"/>:
<input style={{border:'none'}} type="number" name="secondeTime" min="0" max="59" placeholder="00"/>
</form>
const dateString = `${props.editTodoAnswer.inception}T${inceptionValues.firstTime.padStart(2,'0')}:${inceptionValues.secondeTime.padStart(2,'0')}:00`
and i think props.editTodoAnswer.inception may not be in inceptionValues just use props.editTodoAnswer.inception
It is not clear where you want the date string to be outputted... So I assumed you wished it in in the state.
There are three cases in order to build the string, depending on which input changed. Additionally, you have to add the leading zeros.
I suggest you to apply the change handler on each inputs instead of the form. This will allow each inputs to be updated with the state value at each render allowing the leading zeros to be shown.
Have a look at the comments throughout the code.
function CustomDate() {
// Default state values
const inceptionValues = {
date: "2022-02-20",
hours: "00",
minutes: "00",
dateString: "2022-02-20T00:00:00"
};
// State hook
const [inceptionTest, setInceptionTest] = React.useState(inceptionValues);
// Add the leading zeros when necessary
const leadZero = (n) => {
return parseInt(n) < 10 ? `0${n}` : n;
};
// Change handler for the 3 inputs
// so e.target can be any of the 3 inputs
const handleChangeInception = (e) => {
let value = e.target.value;
let newdateString;
// Build the date string
if (e.target.name === "date") {
newdateString = `${value}T${inceptionTest.hours}:${inceptionTest.minutes}:00`;
}
if (e.target.name === "hours") {
value = leadZero(value);
newdateString = `${inceptionTest.date}T${value}:${inceptionTest.minutes}:00`;
}
if (e.target.name === "minutes") {
value = leadZero(value);
newdateString = `${inceptionTest.date}T${inceptionTest.hours}:${value}:00`;
}
// Prepare the object to set the new state
let newState = {
...inceptionTest,
[e.target.name]: value,
dateString: newdateString
};
console.log(newState);
setInceptionTest(newState);
};
// Render
return (
<form>
<input
style={{ margin: "0 5px 0 0" }}
type="date"
name="date"
value={inceptionTest.date}
onChange={(e) => handleChangeInception(e)}
/>
<input
style={{ border: "none" }}
type="number"
name="hours"
min="0"
max="23"
placeholder="23"
value={inceptionTest.hours}
onChange={(e) => handleChangeInception(e)}
/>
:
<input
style={{ border: "none" }}
type="number"
name="minutes"
min="0"
max="59"
placeholder="00"
value={inceptionTest.minutes}
onChange={(e) => handleChangeInception(e)}
/>
</form>
);
}
class App extends React.Component {
render() {
return (
<div className="App">
<h1>Custom date</h1>
<CustomDate />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<div id="root"></div>
import { useState } from "react";
import "./styles.css";
function App() {
const [InputVal, setInputVal] = useState();
const [ShowDiv, setShowDiv] = useState(
<div>
<p>Hello world. This is default "Show Div" value</p>
</div>
);
const ChangeDivFunc = () => {
setShowDiv(
<div>
<p style={{ color: "red" }}>
Hello World. This is updated "Show Div" value
</p>
<input onChange={getInputval} type="text" />
<br />
<br />
<button onClick={AlertVal}>Show Input Value</button>
</div>
);
};
const getInputval = (val) => {
setInputVal(val.target.value);
};
const AlertVal = () => {
alert(InputVal);
};
return (
<div className="App">
<h1>Example</h1>
<br />
<button onClick={ChangeDivFunc}>Change Div</button>
{ShowDiv}
</div>
);
}
export default App;
Code Flow:
Click Change Div button then it will show Input field and Show Input Value button.
Now, Enter some value in input field and click the Show Input Value button to get the value of input field.
Problem:
It returns undefined instead of input field value.
I'm trying to get the value of Input field when Show Input Value button is clicked. But I'm not getting the desired results.
Here's the Sandbox link : Click for Code
Do not store html node inside state. You can simply store only a boolean value to switch between what node to show. I'm not pretty sure but it may cause weird behavior since React internally depends heavily on the DOM/HTML UI Tree (see Managing State).
Try this instead:
import { useState } from "react";
import "./styles.css";
function App() {
const [inputVal, setInputVal] = useState(""); // initialize as empty string.
const [showDiv, setShowDiv] = useState(false);
const changeDivFunc = () => {
setShowDiv(true);
};
const getInputVal = (event) => { // The arg is Event object, not val
setInputVal(event.target.value);
};
const alertVal = () => {
alert(inputVal);
};
return (
<div className="App">
<h1>Example</h1>
<br />
<button onClick={changeDivFunc}>Change Div</button>
{
showDiv? (
<div>
<p style={{ color: "red" }}>
Hello World. This is updated "Show Div" value
</p>
<input value={inputVal} onChange={getInputVal} type="text" />
<br />
<br />
<button onClick={alertVal}>Show Input Value</button>
</div>
) : (
<div>
<p>Hello world. This is default "Show Div" value</p>
</div>
)
}
</div>
);
}
export default App;
Forked Codepen
A working example of my problem can be found at:
https://codepen.io/RyanCRickert/pen/vYYQeaW
I am prop drilling a function two levels and passing that function along with an index to a rendered component. When a name is submitted it renders a new component which shows the name and div which has an onClick (X). I am trying to receive the index of where the name is located in the array which it lives so that I may splice it out when the button is clicked.
If I enter the name "Bob" for example, then click the div with the listener I can console log the event.target. Using the above example I get "<div class='person-item__X' value='0'>X</div>" for event.target and undefined for event.target.value. The value is being assigned as <div onClick={props.removeName} class="person-item__X" value={props.value}>X</div>.
Am I just unable to grab the value of a div in such a manor? Or is there something that I am missing? Thank you
Change these to your code
const PersonListItem = props => (
<div class="person-item">
<div class="person-item__name">{props.name}</div>
<div onClick={() => props.removeName(props.value)} class="person-item__X" value={props.value}>X</div>
</div>
);
Inside PeopleList replace this line
<PersonListItem key={index} name={person} value={index} removeName={(id) => props.removeName(id)} />
Inside TeamGenerator replace this line
<PeopleList people={this.state.names} removeName={(id) => this.handleRemoveName(id)} />
now in handleRemoveName you will recieve a id of the item on which X was clicked
handleRemoveName = id => {
const currentArr = this.state.names;
console.log(id);
}
In your case, to grab the value inside this div, you should use ref API.
Your code should look like this:
TeamGenerator.js
import React, { Component } from "react";
import CustomModal from "./Modal";
import PeopleList from "./PeopleList";
import "./index.css";
export default class App extends Component {
constructor(props) {
super(props);
// Create a ref
this.divTextRef = React.createRef();
this.state = {
names: [],
selectedName: ""
};
}
handleCloseModal = () => {
this.setState({
selectedName: ""
});
};
handleChange = e => {
this.setState({ name: e.target.value });
};
handleRemoveName = index => {
// Get your name and index this way
console.log("Your text: ", this.divTextRef.current.innerHTML);
console.log("Your index: ", index);
};
handleSubmit = e => {
e.preventDefault();
const currentNames = this.state.names;
if (this.state.name)
currentNames.push(
this.state.name[0].toUpperCase() + this.state.name.slice(1)
);
this.setState({
name: "",
names: currentNames
});
};
render() {
return (
<div className="container">
<CustomModal
selectedName={this.state.selectedName}
closeModal={this.handleCloseModal}
/>
<form onSubmit={this.handleSubmit}>
<label>
Add name:
<input
type="text"
value={this.state.name}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
<div className="people-list-container">
<PeopleList
people={this.state.names}
removeName={this.handleRemoveName}
upperRef={this.divTextRef} // Pass the ref down from your Component tree
/>
</div>
</div>
);
}
}
PeopleList.js
import React from "react";
import PersonListItem from "./PersonListItem";
export default class PeopleList extends React.Component {
render() {
return (
<div className="people-container">
<div className="people-title">List of people</div>
<div className="people-list">
{this.props.people.length === 0 ? (
<div className="people-item">
<span>No people added</span>
</div>
) : (
this.props.people.map((person, index) => (
<PersonListItem
key={index}
name={person}
value={index}
removeName={() => this.props.removeName(index)} // Passing index to the removeName function of Parent
upperRef={this.props.upperRef} // Continue passing it down to PersonListItem
/>
))
)}
</div>
</div>
);
}
}
PersonListItem.js
import React from "react";
const PersonListItem = props => (
<div className="person-item">
<div ref={props.upperRef} className="person-item__name"> // Use the passed ref
{props.name}
</div>
<div
onClick={props.removeName}
className="person-item__X"
value={props.value}
>
X
</div>
</div>
);
export default PersonListItem;
The div node does not have the value like input, so you can not grab it by your old way.
My goal is to hide one of my divs or all my p tags until user input actually exists. You can see my attempt below which included a method to change the value of my div state to true or false and whether it's true or false, adjust the display to block or none whether or not the user has inputted anything.
I understand that it would be simple to apply this to a button of some sort but my goal here is to allow React to re-render the div or p elements once the user has typed something in.
My vision was to measure the user input's length, and if it was greater than 0, show my div or p tags.
Within my render section of my code, you'll see a div with three p tags inside. I want those p tags, or even the entire div (if it's easier) to not show until the user starts typing something within the input box.
import React from "react";
class UserInput extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
showElements: false
};
}
handleChange = event => {
this.setState({ value: event.target.value });
};
badRobot = () => {
const newInput = this.state.value;
let badInput = "BLA"
.repeat(newInput.length / 3 + 1)
.substring(0, newInput.length);
return badInput;
};
hideElements = () => {
const userValueLength = this.state.value;
if (userValueLength.length !== 0) {
console.log("it worked");
this.setState({ showElements: true });
}
};
render() {
return (
<div>
<form>
<label>
<p>Say Anything</p>
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
</label>
</form>
<div style={{ display: this.state.showElements ? "block" : "none" }}>
<h3>Good Robot</h3>
<p>I hear you saying {this.state.value}. Is that correct?</p>
<h3>Bad Robot</h3>
<p>I hear you saying {this.badRobot()}. Is that correct?</p>
<h3>Kanyebot 5000</h3>
<p>I'm gonna let you finish but Beyonce is {this.state.value}.</p>
</div>
</div>
);
}
}
export default UserInput;
Checking if the value string differs from the empty string sounds like a good condition for showing the div.
Instead of keeping a boolean in state you could check the value directly in the render method.
class UserInput extends React.Component {
state = {
value: ""
};
handleChange = event => {
this.setState({ value: event.target.value });
};
render() {
const { value } = this.state;
const showDiv = value !== "";
const badInput = "BLA"
.repeat(value.length / 3 + 1)
.substring(0, value.length);
return (
<div>
<form>
<label>
<p>Say Anything</p>
<input
type="text"
value={value}
onChange={this.handleChange}
/>
</label>
</form>
<div style={{ display: showDiv ? "block" : "none" }}>
<h3>Good Robot</h3>
<p>I hear you saying {value}. Is that correct?</p>
<h3>Bad Robot</h3>
<p>I hear you saying {badInput}. Is that correct?</p>
<h3>Kanyebot 5000</h3>
<p>I'm gonna let you finish but Beyonce is {value}.</p>
</div>
</div>
);
}
}
ReactDOM.render(<UserInput />, document.getElementById("root"));
<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>
<div id="root"></div>
You can do conditional rending.
class UserInput extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
showElements: false
};
}
handleChange = (event) => {
const value = event.target.value;
const showElements = value.length > 0 ? true: false;
this.setState({showElements, value});
}
badRobot = () => {
const newInput = this.state.value;
let badInput = 'BLA'.repeat(newInput.length / 3 + 1).substring(0, newInput.length)
return badInput
}
hideElements = () => {
const userValueLength = this.state.value
if (userValueLength.length !== 0) {
console.log("it worked");
this.setState({showElements: true})
}
}
render(){
return(
<div>
<form>
<label>
<p>Say Anything</p>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
</form>
{
this.state.showElements ?
(
<div>
<h3>Good Robot</h3>
<p>I hear you saying {this.state.value}. Is that correct?</p>
<h3>Bad Robot</h3>
<p>I hear you saying {this.badRobot()}. Is that correct?</p>
<h3>Kanyebot 5000</h3>
<p>I'm gonna let you finish but Beyonce is {this.state.value}.</p>
</div>
): null
}
</div>
)
}
}
I made Todo app using react. On clicking enter the todo gets added in array, then on click on entered todo the todo gets stricked-off. Now i am facing problem to edit the entered todo. I want when i double click the entered todo, it converts into editing mode and then i can edit the todo n save it on enter keypress. My code goes like this:
class App extends React.Component {
constructor(){
super();
this.state={
todo:[]
};
};
entertodo(keypress){
var Todo=this.refs.inputodo.value;
if( keypress.charCode == 13 )
{
this.setState({
todo: this.state.todo.concat({Value:Todo, checked:false, editing:false})
});
this.refs.inputodo.value=null;
};
};
todo(todo,i){
return (
<li className={todo.checked===true? 'line':'newtodo'}>
<div onClick={this.todoCompleted.bind(this, i)}>
<input type="checkbox" className="option-input checkbox" checked={todo.checked} />
<div key={todo.id} className="item">
{todo.Value}
<span className="destroy" onClick={this.remove.bind(this, i)}>X</span>
</div>
</div>
</li>
);
};
remove(i){
this.state.todo.splice(i,1)
this.setState({todo:this.state.todo})
};
todoCompleted(i){
var todo=this.state.todo;
todo[i].checked =todo[i].checked? false:true;
this.setState({
todo:this.state.todo
});
};
allCompleted=()=>{
var todo = this.state.todo;
var _this = this
todo.forEach(function(item) {
item.className = _this.state.finished ? "newtodo" : "line"
item.checked = !_this.state.finished
})
this.setState({todo: todo, finished: !this.state.finished})
};
render() {
return (
<div>
<h1 id='heading'>todos</h1>
<div className="lines"></div>
<div>
<input type="text" ref= "inputodo" onKeyPress={this.entertodo.bind(this)}className="inputodo"placeholder='todos'/>
<span onClick={this.allCompleted}id="all">^</span>
</div>
<div className="mainapp">
<ul className="decor">
{this.state.todo.map(this.todo.bind(this))}
</ul>
</div>
</div>
);
}
}
ReactDOM.render(<App/>,document.getElementById('app'));
.line {
text-decoration: line-through;
color: red;
}
.newtodo{
text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
I've been trying something similar, so this gist might help you on the right track. I think you're especially interested the handleClick method. It debounces received click events. Then you can listen for a certain amount of consecutive clicks, like I did on line 33.
However, the transition between view and edit seems to be quite slow (maybe I did something wrong :shrug:) , so if editing should happen frequently, it might be better to fake this behavior with css.*
Style an input type to look like ordinary text, then onFocus, style it like a field.
There is an option for the click events called onDoubleClick={this.handler} at this point in time.
you may use the component
import _ from 'lodash'
import { useState } from 'react'
const inputValue = (e: any): string => e.target.value
function isEnterOrEscapeKeyEvent(event: React.KeyboardEvent<HTMLInputElement>) {
return event.key === 'Enter' || event.key === 'Escape'
}
const EditOnDblClick = () => {
const [isEditing, setisEditing] = useState(false)
const [text, settext] = useState('yoga chitta')
const onEditEnd = () => {
setisEditing(false)
}
return isEditing ? (
<input
value={text}
className="bg-transparent border-2 border-black border-solid"
onKeyDown={(event) => {
if (isEnterOrEscapeKeyEvent(event)) {
event.preventDefault()
event.stopPropagation()
onEditEnd()
}
}}
onChange={_.flow(inputValue, settext)}
onBlur={onEditEnd}
autoFocus
/>
) : (
<div className="select-none" onDoubleClick={() => setisEditing(true)}>
{text}
</div>
)
}
export default EditOnDblClick
Note: Classes are from tailwindcss