I am working in React with components, but I am not getting functions working in the Input component.
I have tried searching on component and onChange or onKeyPress but they do not show what I need. Maybe I'm searching wrong? I did get the component Button working, just not Input.
The code for the component is simple.
import React from 'react';
import styles from './Input.module.css';
function Input({inputText}) {
return <input type='number'
placeholder={inputText}
className={styles.input}
/>
}
export default Input;
The full code I want to use for component Input is as follows.
import React, {useState} from 'react';
import styles from './Food.module.css';
import axios from 'axios';
import Nutrients from '../../components/nutrients/Nutrients'
import {ReactComponent as LoadingIcon} from '../../assets/loading.svg'
import Button from "../../components/button/Button";
import Input from "../../components/input/Input";
function Food() {
const [food, setFood] = useState(null);
const [calories, setCalories] = useState('');
const [disabled, setDisabled] = useState(false);
const [error, setError] = useState('');
const [loading, toggleLoading] = useState('');
async function foodData() {
setError('');
toggleLoading('true')
try {
const result = await axios.get(`https://api.spoonacular.com/mealplanner/generate?apiKey=${process.env.REACT_APP_API_KEY}&timeFrame=day&targetCalories=${calories}`);
setFood(result.data);
} catch (error) {
setError('Oops... something went wrong. Please try again.');
console.log('Something went wrong while retrieving the data.', error);
}
toggleLoading(false);
}
function handleChange(e) {
setCalories(e.target.value);
}
function handleKeyPress(e) {
if (e.key === 'Enter') {
if (disabled) {
return;
}
foodData();
setDisabled(true);
}
}
return (
<>
{error && <p className={styles.error}>{error}</p>}
<div>
<section className={styles.food}>
<Input
inputText='Enter caloriessss'
onChange= {handleChange}
onKeyPress={handleKeyPress}
/>
<Button
onClick={() => {
foodData();
setDisabled(true);
}}
buttonText='Click for your daily meals'
/>
</section>
{loading && <LoadingIcon className={styles.loader}/>}
{food && <Nutrients mealsData={food}/>}
</div>
</>
);
}
export default Food;
The thing I want is for the two functions onChange and onKeyPress to work in the Input component.
Anyone has any ideas? I also tried using () and ''.
Because you don't use props onChange and onKeyPress in Input component. Just add it like this:
function Input({ inputText, onChange, onKeyPress }) {
return (
<input
type="number"
placeholder={inputText}
className={styles.input}
onChange={onChange}
onKeyPress={onKeyPress}
/>
);
}
Or shorter way:
function Input({ inputText, ...props }) {
return (
<input
type="number"
placeholder={inputText}
className={styles.input}
{...props}
/>
);
}
React has no way of knowing the onChange and onKeyPress props should be passed to the input inside of your Input component.
You must pass them along explicitly.
// Add them to your destructured props
function Input({inputText, onChange, onKeyPress}) {
return <input type='number'
onChange={onChange} // Pass them to the input
onKeyPress={onKeyPress} // Pass them to the input
placeholder={inputText}
className={styles.input}
/>
}
In the component Input, your return should be: <input></input>
Because JSX needs to closed tags.
Related
In this simple "demo" in CodeSandbox: https://codesandbox.io/s/cool-fast-fi426k?file=/src/App.tsx
you can see that checked actually changes, based on an external condition (inputted text length), but this does not "physically"change the Switch
import "./styles.css";
import * as React from "react";
import { Switch } from "antd";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit } = useForm();
let [checked, setChecked] = React.useState(false);
const onSubmit = (data: string) => {
console.log("data.text: ", data.text);
let length = data.text.length;
console.log("data.text.length: ", length);
if (length > 5) {
console.log("'checked' variable has to be set as TRUE");
setChecked((checked) => true);
} else {
console.log("'checked' variable has to be set as FALSE");
setChecked((checked) => false);
}
};
const AntdOnChange = (checked) => {
console.log(`switch to ${checked}`);
};
React.useEffect(() => {
AntdOnChange(checked);
}, [checked]);
return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="text">Text</label>
<input id="text" placeholder="text" {...register("text")} />
</div>
<button type="submit">Submit</button>
</form>
<Switch
checkedChildren="ON"
unCheckedChildren="OFF"
defaultChecked
onChange={AntdOnChange}
/>
</div>
);
}
How to pass the correctly changed value of checked variable to the Switch state ?
You can achieve this by doing three things
Remove the useEffect that updates the checked state. If you pass the state into the switch component with that, it will cause multiple renders which will cause an error
Do this in your switch component. I have added the checked prop
<Switch
checkedChildren="ON"
unCheckedChildren="OFF"
defaultChecked
checked={checked}
onChange={AntdOnChange}
/>
In your AntdOnChange function, do this. This function will work independently of whatever is added in the input
const AntdOnChange = (checked) => {
setChecked((checked) => !checked);
};
I'm new to React and still am trying to make sense of a few things. I'm using the react-form-dom library and after looking into the documentation I can't figure out what's going on with my project.
I have created a custom input component that takes in a few parameters. The problem is that when I try to log the value of the inputs I get undefined.
Input.jsx
import React, { useState } from 'react';
import './Input.scss';
export default function Input(props, {register, errors}) {
const [inputVal, setInputVal] = useState('');
const nameChange = (e) => {
setInputVal(e.target.value);
props.nameChange(e.target.value);
}
const legend = <span className='legend'>{props?.legend}</span>;
const showLength = <span className='legend'>{props.maxLength - inputVal.length}</span>;
return (
<div className="input-holder">
<input
ref={register}
type={props.type || 'text'}
id={props.id}
placeholder={props.placeholder}
value={inputVal}
onInput={nameChange}
maxLength={props.maxLength || ""}
/>
{ props.legend ? legend : null}
{ props.showLength && props.maxLength ? showLength : null }
</div>
)
}
Form.jsx
import React from 'react';
import { useForm } from "react-hook-form";
import Button from './Button';
import Input from './Input';
export default function UserForm(props) {
const { register, handleSubmit } = useForm();
function submitForm(data) {
console.log(data)
}
return (
<div className="user-form">
<form onSubmit={handleSubmit(submitForm)}>
<Input
placeholder="Name"
nameChange={(name) => props.userName(name)}
showLength="true"
maxLength="35"
legend="Remaining Char: "
id="name"
register={register}
/>
<Input
placeholder="E-mail"
type="email"
id="email"
register={register}
/>
<Button label="Buy" />
</form>
</div>
)
}
It seems that you are using react-hook-form
Checkout the example here
The onChange you are passing to the input tags are no longer needed with react-hook-form beacuse of register functionality of react-hook-form
also validations will be done react-hook-form
import React from 'react';
import { useForm } from "react-hook-form";
export default function UserForm(props) {
const { register, handleSubmit } = useForm();
const submitForm = (data) => {
console.log(data);
}
const onError = (err) => {
console.error(err);
}
return (
<div className="user-form">
<form onSubmit={handleSubmit(submitForm, onError)}>
<input
{...register("name", { //handles onChange, value, name, ref
maxLength: 35 // Your validations
})}
/>
<button>Buy</button>
</form>
</div>
)
}
Checkout docs for register
Form File Example
im trying to show the p element when the input filed has value "the user writes something in input field" and hides when the input is empty
import React, {useState} from 'react'
function textInput() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<input type="text" onKeyUp={() => setIsOpen(!isOpen)} />
{
isOpen ?
<p>result</p>
: null
}
</>
)
}
export default textInput
Rather than using an isOpen prop, consider maintaining the text in state. Then, if the text is not empty, show the <p> component:
import React, { useState } from "react";
function textInput() {
const [text, setText] = useState("");
return (
<>
<input
type="text"
value={text}
onChange={(e) => {
setText(e.target.value);
}}
/>
{text && <p>result</p>}
</>
);
}
export default textInput;
Please write code like below. It works.
import React, { useState } from "react";
function textInput() {
const [inputText, setInputText] = useState("")
return (
<>
<input type="text" onChange={ (e) => {
setInputText(e.target.value)
}
}/>
{ (inputText !== "") && <p>result: {inputText}</p> }
</>
)
}
export default textInput;
When I submit text in the form, I want to be able to see that text in state via console.log.
I added a console.log to trigger directly after state has been added, but I don't see anything in my console, what am I doing wrong?
What I would like to see: I submit "test1" then I submit "test2", I then want to see in my console "test1, test2" in state.
import React, { useState } from 'react';
import './App.css';
function App() {
return (
<div>
<Field />
</div>
);
}
function Field(){
const [toDoItem, setToDoItem] = useState('');
const addToDoItem = (event) => {
setToDoItem(event.target.value), function(){
console.log(toDoItem)
}
}
return (
<form>
<input type="text" value={toDoItem} onChange={addToDoItem}/>
<input type="submit" value="Add" />
</form>
);
}
export default App;
You can log the change in states using a useEffect
I'd suggest making a helper function if you tend to do it often:
function useLog(name, property) {
useEffect(() => console.log(name, property), [name, property]);
}
Which you'd use as follows:
useLog('toDoItem', toDoItem);
I set up an example where the toDoItem is logged as it changes and when you submit, it also logs the change in a todoItems array
const { useState, useEffect } = React;
function useLog(name, property) {
useEffect(() => console.log(name, property), [name, property]);
}
function App() {
return (
<div>
<Field />
</div>
);
}
function Field() {
const [toDoItem, setToDoItem] = useState('');
useLog('toDoItem', toDoItem);
const [todos, setTodos] = useState([]);
useLog('todos', todos);
const changeTodo = (event) => {
setToDoItem(event.target.value);
};
const addTodoItem = (event) => {
event.preventDefault();
setTodos((prev) => prev.concat(toDoItem));
setToDoItem('');
};
return (
<form onSubmit={addTodoItem}>
<input type="text" value={toDoItem} onChange={changeTodo} />
<input type="submit" value="Add" />
</form>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"/>
useState doesn't provide callback after setting value. You can use useEffect instead.
React.useEffect(() => {
console.log(toDoItem);
}, [toDoItem]);
EDIT
It seems like that you want to get toDoItem value on submit. The problem is that the page is reloaded when form is submitted. You can use event.prefentDefault() to stop refreshing on form submission.
<form onSubmit={onSubmit}>
const onSubmit = (event) => {
event.preventDefault()
console.log(toDoItem)
}
import React, { useState } from 'react';
import './App.css';
function App() {
return (
<div>
<Field />
</div>
);
}
function Field(){
const [toDoItem, setToDoItem] = useStateWithCallback('', toDoItem => {
console.log(toDoItem);
});
const addToDoItem = (event) => {
setToDoItem(event.target.value);
}
return (
<form>
<input type="text" value={toDoItem} onChange={addToDoItem}/>
<input type="submit" value="Add" />
</form>
);
}
export default App;
I believe it is because it binds the value back to the property inputText but just want to make sure I'm stating this correctly.
import React, { useState } from "react";
const InputElement = () => {
const [inputText, setInputText] = useState("");
return (
<div>
<input
placeholder="Enter Some Text"
onChange={e => {
setInputText(e.target.value);
}}
/>
</div>
);
};
export default InputElement;
This is a good example of 2 way data binding because when you update the state, the UI changes, and when the UI changes, the state changes. Just need to remind you to set the value prop on the <input> element to inputText so that it's a controlled component.
import React, { useState } from "react";
const InputElement = () => {
const [inputText, setInputText] = useState("");
return (
<div>
<input
placeholder="Enter Some Text"
onChange={e => {
setInputText(e.target.value);
}}
value={inputText}
/>
</div>
);
};
export default InputElement;