How to render functional component with props - javascript

I'm trying to render a component as a child passing the parent props, but page doesn't show anything, just white. When I take out the part of the code that uses the props, it renders. I'm trying to pass a state var and a function. Thanks :)
const MainButtons = (props) => {
const { depositAmount } = props;
return (
<div className="container1">
<form
className="deposit"
onSubmitCapture={(event) => {
event.preventDefault();
const depositAmount = depositAmount;
props.deposit(depositAmount);
}}
>
<input
type="text"
className="inputs"
placeholder="Amount to deposit"
ref={(input) => (depositAmount = input)}
/>
<button className="btnS btnS-colored">
<BsArrowBarUp />
Send
</button>
</form>
</div>
);
};
And the parent renders this:
<MainButtons
depositAmount={this.state.depositAmount}
deposit={this.deposit}
/>

Related

How do I get the Age data from child to parent component

Parent.js
import React, { useState } from 'react'
import Child from './Child'
const Parent = () => {
const[data,setData] = useState('')
const[name,setName] = useState('')
const[toggled,setToggled] = useState(false)
const[age,setAge] = useState('')
const ageToChild = (ageData) =>{
setAge(ageData)
}
const childToParent = (childData) =>{
setData(childData)
}
const handleSubmit = (e) =>{
e.preventDefault()
alert(`Age is ${age} , Form Submitted`)
console.log(`Name is ${name} and Age is ${age}`)
}
return (
<>
{data}
<div>
{/* <Child childToParent={childToParent}></Child> */}
<form onSubmit={handleSubmit}>
<label>Name : </label>
<input type="text" value={name} onChange={(e)=>setName(e.target.value)}></input>
<button type='button' onClick={()=>setToggled(!toggled)}>Age ?</button>
{toggled && <Child childToParent={childToParent} ageToChild={ageToChild}></Child>}
<button type='button'>Submit</button>
</form>
</div>
</>
)
}
export default Parent
Child.js
import React from 'react'
const Child = ({childToParent,ageToChild}) => {
const data = "This is some data from the child component to parent"
// const age = ageToChild
return (
<>
<button onClick={()=>childToParent(data)}>Click Child</button>
<label>Age : </label>
<input type='text' onChange={()=>ageToChild()}></input>
</>
)
}
export default Child
I am getting output as Name is inputtedname and Age is Undefined , How do I get the user inputted age value logged in the console?
I am trying to pass data from child to parent using functional components
If you want to pass age value to alert() from Child.js component, you should add e.target.value to onChange:
<input type='text' onChange={(e)=>ageToChild(e.target.value)}></input>
Make sure to pass the ageToChild function from the parent component to the child:
<Child childToParent={childToParent} ageToChild={ageToChild} />
Then from the Child component you can simply do:
<input type='text' onChange={(e)=> ageToChild(e.target.value)} />
use this code:
<input type='text' onChange={(e)=>ageToChild(e.target.value)}></input>
You have forgotten to pass the value in the function😁. Try passing it in onChange.
onChange={(e)=>ageToChild(e.target.value)}

Reactjs: How to access state of child component.from a method in parent component that depends on state of child component

I need to access a method handleCancelEdit() defined in parent component. But, the matter here is that every child component will have its own cancelEdit state. Now, what is happening is, if I call handleCancelEdit() from one child component, every other of the same child components is taking the state and updating themselves(the method is not completely defined yet). That's why, I have defined the cancelEdit state in the child component, thinking that it belongs to this child component only.
Now, how do I make the handleCancelEdit() method make changes to the only child component which called it?
The parent:
function Parent() {
const handleCancelEdit = () => {
setCancelEdit(!cancelEdit); // defined in child component
setEdit(!edit); // defined in child component
...
};
return (
<div>
<ChildComponent
fieldName={"Email"}
value={email}
inputType={"text"}
placeHolder={"Enter email"}
name={"email"}
on_change={(e)=>setEmail(e.target.value)}
on_click={handleUserEmail}
/>
<ChildComponent
fieldName={"About"}
value={about}
inputType={"text"}
placeHolder={"Enter some details about yourself"}
name={"about"}
on_change={(e)=>setAbout(e.target.value)}
on_click={handleUserAbout}
/>
</div>
);
}
Child component:
function ChildComponent({fieldName, value, inputType, placeHolder, name, on_change, on_click}) {
const [ edit, setEdit ] = useState(false);
const [ cancelEdit, setCancelEdit ] = useState(false)
const isEdit = edit;
return (
<p>{fieldName}: {value === ''? (
<span>
<input type={inputType} placeholder={placeHolder}
name={name} onChange={on_change}
/>
<button type="submit" onClick={on_click}>Add</button>
</span>
) : ( !isEdit ? (<span> {value} <button onClick={e=>setEdit(!edit)}>Edit</button></span>) :
(<span>
<input type={inputType} value={value}
name={name} onChange={on_change}
/>
<button type="submit" onClick={on_click}>Save</button>
<button type="submit" onClick={handleCancelEdit}>Cancel</button>
</span>)
)}
</p>
);
};
I hope it could make it understandable that one child component should not make others to update. Now, how do I do it in this scenario?
EDIT
After making changes according to Linda Paiste:
The input field in the child component is not working even though the onChange in both parent and child is correct!
It is always more logical to pass state and data down rather than up. If the Parent needs to interact with the edit state then that state should live in the parent. Of course we want independent edit states for each child, so the parent can't just have one boolean. It needs a boolean for each child. I recommend an object keyed by the name property of the field.
In ChildComponent, we move isEdit and setEdit to props. handleCancelEdit is just () => setEdit(false) (does it also need to clear the state set by onChange?).
function ChildComponent({fieldName, value, inputType, placeHolder, name, onChange, onSubmit, isEdit, setEdit}) {
return (
<p>{fieldName}: {value === ''? (
<span>
<input type={inputType} placeholder={placeHolder}
name={name} onChange={onChange}
/>
<button type="submit" onClick={onSubmit}>Add</button>
</span>
) : ( !isEdit ? (<span> {value} <button onClick={() =>setEdit(true)}>Edit</button></span>) :
(<span>
<input type={inputType} value={value}
name={name} onChange={onChange}
/>
<button type="submit" onClick={onSubmit}>Save</button>
<button type="submit" onClick={() => setEdit(false)}>Cancel</button>
</span>)
)}
</p>
);
};
In Parent, we need to store those isEdit states and also create a setEdit function for each field.
function Parent() {
const [isEditFields, setIsEditFields] = useState({});
const handleSetEdit = (name, isEdit) => {
setIsEditFields((prev) => ({
...prev,
[name]: isEdit
}));
};
/* ... */
return (
<div>
<ChildComponent
fieldName={"Email"}
value={email}
inputType={"text"}
placeHolder={"Enter email"}
name={"email"}
onChange={(e) => setEmail(e.target.value)}
onSubmit={handleUserEmail}
isEdit={isEditFields.email}
setEdit={(isEdit) => handleSetEdit("email", isEdit)}
/>
<ChildComponent
fieldName={"About"}
value={about}
inputType={"text"}
placeHolder={"Enter some details about yourself"}
name={"about"}
onChange={(e) => setAbout(e.target.value)}
onSubmit={handleUserAbout}
isEdit={isEditFields.about}
setEdit={(isEdit) => handleSetEdit("about", isEdit)}
/>
</div>
);
}
You can clean up a lot of repeated code by storing the values as a single state rather than individual useState hooks. Now 5 of the props can be generated automatically just from the name.
function Parent() {
const [isEditFields, setIsEditFields] = useState({});
const [values, setValues] = useState({
about: '',
email: ''
});
const getProps = (name) => ({
name,
value: values[name],
onChange: (e) => setValues(prev => ({
...prev,
[name]: e.target.value
})),
isEdit: isEditFields[name],
setEdit: (isEdit) => setIsEditFields(prev => ({
...prev,
[name]: isEdit
}))
});
const handleUserEmail = console.log // placeholder
const handleUserAbout = console.log // placeholder
return (
<div>
<ChildComponent
fieldName={"Email"}
inputType={"text"}
placeHolder={"Enter email"}
onSubmit={handleUserEmail}
{...getProps("email")}
/>
<ChildComponent
fieldName={"About"}
inputType={"text"}
placeHolder={"Enter some details about yourself"}
onSubmit={handleUserAbout}
{...getProps("about")}
/>
</div>
);
}

How to reset input field from useRef in React?

I have a text input. If I click on a specific button in the page, I want to reset the value of the input. Here is my code:
const inputRef = useRef()
const handleClick= () => {
inputRef.current.value.reset();
return "hello world"
}
return (
<>
<input type="text" ref={inputRef}/>
<button onClick={()=> handleClick}>delete all</button>
</>
)
It doesn't work. How to fix this?
reset is available on form element.
You can wrap your input with a form, and trigger reset on it.
const {useRef} = React;
const App = () => {
const formRef = useRef();
const handleClick = () => {
formRef.current.reset();
};
return (
<form ref={formRef}>
<input type="text" />
<input type="password" />
<input type="checkbox" />
<textarea></textarea>
<button onClick={handleClick} type="button">
clear form
</button>
</form>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can clear the value in the input field like below.
const handleClick= () => {
inputRef.current.value = "";
return "hello world"
}
and change onClick call in the button like below
onClick={handleClick}
//or
onClick={()=> handleClick()}
If you want complete reset of a form having multiple inputs, you can follow the below approach.
In below example, form will reset after submit
const formRef = useRef();
const handleClick = () => {
formRef.current.reset();
}
render() {
return (
<form ref={formRef}>
<input />
<input />
...
<input />
</form>
);
}
if you don't want to use Ref
const handleSubmit = e => {
e.preventDefault();
e.target.reset();
}
<form onSubmit={handleSubmit}>
...
</form>
You can clear the text input field by setting its value to an empty string. You can do that like this inputref.current.value = "" if you want to use uncontrolled inputs.
However, if you want to use controlled inputs you can create a state variable to track the value of the input field. For example,
const SomeComponent = () => {
const [text, setText] = useState('')
return (
<>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
<button onClick={() => setText('')}>delete all</button>
</>
);
};
Here is a codesandbox with both implementation.
You have two problems, one you are passing a function that calls a function into your onClick handler -- which isn't needed. If you define the function before your render, you do not need to pass an anonymous function to the onClick handler.
// Before
<button onClick={()=> handleClick}>delete all</button>
// After
<button onClick={handleClick}>delete all</button>
The other problem is that your handleClick function calls reset, which is not a function on an input. To reset the value of the referenced input, you can set it to an empty string (or whatever you want the "default" value to be).
const handleClick = e => {
inputRef.current.value = "";
return "hello world";
};
rest value in input
import { useRef } from 'react'
const Test = () => {
const testRef = useRef(null)
return (
<div>
<input type="text" ref={testRef} />
<button onClick={() => inputSearch.current.value = ''}>×</button>
</div>
)
}
export default Test

Store Values from Material UI's form in TypeScript

What's the best way to store values typed into the text fields here?
const AddUserPage = () => (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<div className='main-content'>
<form className="ROOT" noValidate autoComplete="off">
<TextField id="standard-basic" label="Standard" />
</form>
</div>
</div>
);
export default AddUserPage;
I want to find a way such that I can use the stored values in my GraphQL mutations as well, without having to modify the const() structure of my page. I don't want to use the Class Component Extend or function structure here.
What is your const() structuremakes:
=> (This is the auto return syntax.)
If you want to store/reuse your value, you will have to define some state/variable to store the data.
You can also do it in upper component like:
import React, { useState } from "react";
const Parent = props => {
const [state, setState] = useState({ text: "" });
return <AddUserPage value={state.text} onChange={e => setState(prev => ({ ...prev, text: e.target.value || "" }))} />
}
const AddUserPage = ({ value = "" , onChange }) => (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<div className='main-content'>
<form className="ROOT" noValidate autoComplete="off">
<TextField id="standard-basic" value={value} onChange={onChange} label="Standard" />
// value, and Onchange comes from an upper component
</form>
</div>
</div>
);

Clear an input field with Reactjs?

I am using a variable below.
var newInput = {
title: this.inputTitle.value,
entry: this.inputEntry.value
};
This is used by my input fields.
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<textarea id="inputage" ref={el => this.inputEntry = el} className="form-control" />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
Once I activate {this.sendthru} I want to clear my input fields. However, I am uncertain how to do so.
Also, as shown in this example, it was pointed out to me that I should use the ref property for input values. What I am unclear of is what exactly does it mean to have {el => this.inputEntry = el}. What is the significance of el in this situation?
Let me assume that you have done the 'this' binding of 'sendThru' function.
The below functions clears the input fields when the method is triggered.
sendThru() {
this.inputTitle.value = "";
this.inputEntry.value = "";
}
Refs can be written as inline function expression:
ref={el => this.inputTitle = el}
where el refers to the component.
When refs are written like above, React sees a different function object each time so on every update, ref will be called with null immediately before it's called with the component instance.
Read more about it here.
Declare value attribute for input tag (i.e value= {this.state.name}) and if you want to clear this input value you have to use this.setState({name : ''})
PFB working code for your reference :
<script type="text/babel">
var StateComponent = React.createClass({
resetName : function(event){
this.setState({
name : ''
});
},
render : function(){
return (
<div>
<input type="text" value= {this.state.name}/>
<button onClick={this.resetName}>Reset</button>
</div>
)
}
});
ReactDOM.render(<StateComponent/>, document.getElementById('app'));
</script>
I'm not really sure of the syntax {el => this.inputEntry = el}, but when clearing an input field you assign a ref like you mentioned.
<input type="text" ref="someName" />
Then in the onClick function after you've finished using the input value, just use...
this.refs.someName.value = '';
Edit
Actually the {el => this.inputEntry = el} is the same as this I believe. Maybe someone can correct me. The value for el must be getting passed in from somewhere, to act as the reference.
function (el) {
this.inputEntry = el;
}
I have a similar solution to #Satheesh using React hooks:
State initialization:
const [enteredText, setEnteredText] = useState('');
Input tag:
<input type="text" value={enteredText} (event handler, classNames, etc.) />
Inside the event handler function, after updating the object with data from input form, call:
setEnteredText('');
Note: This is described as 'two-way binding'
You can use input type="reset"
<form action="/action_page.php">
text: <input type="text" name="email" /><br />
<input type="reset" defaultValue="Reset" />
</form>
Now you can use the useRef hook to get some magic if you do not want to use the useState hook:
function MyComponent() {
const inputRef = useRef(null);
const onButtonClick = () => {
// #ts-ignore (us this comment if typescript raises an error)
inputRef.current.value = "";
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Clear input</button>
</>
);
}
As I mentioned, if you are using useState that is the best way. I wanted to show you also this special approach.
Also after React v 16.8+ you have an ability to use hooks
import React, {useState} from 'react';
const ControlledInputs = () => {
const [firstName, setFirstName] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
if (firstName) {
console.log('firstName :>> ', firstName);
}
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="firstName">Name: </label>
<input
type="text"
id="firstName"
name="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<button type="submit">add person</button>
</form>
</>
);
};
You can use useState:
import React, { useState } from 'react';
const [inputTitle, setInputTitle] = useState('');
then add value to your input component:
render() {
<input type="text" onChange={(e) => setInputTitle(e.target.value)}
value={inputTitle} />
<button onClick={handleSubmit} type="submit">Submit</button>
}
On your submit handler function:
setInputTitle('');
document.querySelector('input').defaultValue = '';
On the event of onClick
this.state={
title:''
}
sendthru=()=>{
document.getElementByid('inputname').value = '';
this.setState({
title:''
})
}
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
I used the defaultValue property, useRef, and onClick to achieve this.
let ref = useRef()
and then inside the return:
<input type="text" defaultValue="bacon" ref={ref} onClick={() => ref.current.value = ""} />
also if you want to use onChange for the input it wouldn't require any more configuration and you can just use it. If you want to have a dynamic defaultValue then you absolutely can, with useState.
A simple way to reset the input in React is by implementing the onBlur inside the input.
onBlur={cleanSearch}
ej:
const [search, setSearch] = useState('')
const handleSearch = ({target}) =>{
setSearch(target.value)
}
const cleanSearch = () =>setSearch('')
<input
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
value={search}
onChange={handleSearch}
onBlur={cleanSearch}
/>
The way I cleared my form input values was to add an id to my form tag.
Then when I handleSubmit I call this.clearForm()
In the clearForm function I then use document.getElementById("myForm").reset();
import React, {Component } from 'react';
import './App.css';
import Button from './components/Button';
import Input from './components/Input';
class App extends Component {
state = {
item: "",
list: []
}
componentDidMount() {
this.clearForm();
}
handleFormSubmit = event => {
this.clearForm()
event.preventDefault()
const item = this.state.item
this.setState ({
list: [...this.state.list, item],
})
}
handleInputChange = event => {
this.setState ({
item: event.target.value
})
}
clearForm = () => {
document.getElementById("myForm").reset();
this.setState({
item: ""
})
}
render() {
return (
<form id="myForm">
<Input
name="textinfo"
onChange={this.handleInputChange}
value={this.state.item}
/>
<Button
onClick={this.handleFormSubmit}
> </Button>
</form>
);
}
}
export default App;

Categories