How to access the html component from a composite component in react? - javascript

Consider this component
var React = require("react");
var Input = React.createClass({
render:function(){
return (<input {...this.props}/>)
}
})
module.exports = Input;
This is another component which uses the first component
var React = require('react');
var Button = require('./Button.react');
var Input = require('./Input.react');
var Form = React.createClass({
render:function(){
return( <div>
<Input ref = {(input) => this._user=input} placeholder='Username'/>
<Input ref = {(input) => this._pass=input} type="password" placeholder='Password'/>
<Button onClick={this.onPress}>Login</Button>
</div> )
},
onPress:function(){
console.log(this._user.value);
}
});
module.exports = Form;
I want to access the value property of the <input /> of the first component. I understand that only the component constructor is available in the callback function provided for ref attribute.
So is there any way I can access the html component within the second component ?
I apologise if this question is duplicate , I am new to react and unfamiliar with the terminology.

You can use refs
<Input ref = {(input) => this._pass=input} type="password" placeholder='Password'/>
and then
this._pass.yourValueFunction()
However, I suspect this is not what you want to do. You're trying to get the value from <Input />, but that should be done with onChange callback from <Input /> that's setting the value in its parent.
Something like...
var Input = React.createClass({
render() {
return <input {...this.props} onChange={this.props.handleChange} />
}
})
and in your parent you need to define handleChange callback, for example
handleChange(e) {
this.setState({ inputValue: e.target.value })
// or possibly this.inputValue = inputValue
}
and pass it to the <Input />
<Input handleChange={handleChange} ... />
Then the <Input /> value will always be accessible: this.state.inputValue

Related

How to render functional component with props

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}
/>

datetime-local in react component

There is a component:
class DatetimeFilter extends Component {
constructor(props) {
super(props);
this.changeFromTimeTaskEducation = this.props.changeFromTimeTaskEducation;
this.changeToTimeTaskEducation = this.props.changeToTimeTaskEducation;
}
changeFromTimeTaskEducation = (event) => {
// change value in parent
};
changeToTimeTaskEducation = (event) => {
// change value in parent
};
render() {
return (
<input onChange={this.changeFromTimeTaskEducation} className="filter_datetime_second_value"
type="datetime-local" value={this.props.fromTimeTaskEducation}/>
<input onChange={this.changeToTimeTaskEducation} className="filter_datetime_second_value"
type="datetime-local" value={this.props.toTimeTaskEducation}/>
);
}
}
export default DatetimeFilter;
When I try to change the value in the input, an exception appears:
Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.
How can this be solved?
I tried setting defaultValue, but it only initializes once.
if you think you must have a value, set it as defaultValue and onChange maintain state
<input onChange={this.changeFromTimeTaskEducation} className="filter_datetime_second_value"
type="datetime-local" defaultValue={this.props.fromTimeTaskEducation}/>
<input onChange={this.changeToTimeTaskEducation} className="filter_datetime_second_value"
type="datetime-local" defaultValue={this.props.toTimeTaskEducation}/>
Implement an OnChange function that calls the parent (prop) functions. You are overwriting the functions from the parents with your local function definitions.
Here is a proper way to do what you want:
class DatetimeFilter extends Component {
localFromTimeTaskEducation = (event) => {
this.props.changeFromTimeTaskEducation(event.target.value); //Or whatever value you are trying to pass
}
localToTimeTaskEducation = (event) => {
this.props.changeToTimeTaskEducation(event.target.value);
}
render() {
return (
<input
onChange={this.localFromTimeTaskEducation}
className="filter_datetime_second_value"
type="datetime-local"
value={this.props.fromTimeTaskEducation}
/>
<input
onChange={this.localFromTimeTaskEducation}
className="filter_datetime_second_value"
type="datetime-local"
value={this.props.toTimeTaskEducation}
/>
);
}
}
export default DatetimeFilter;

Rails/React: Refs Must Have Owner

I am using the react-rails gem. In my component I have two input fields with a ref each. However, the console throws me the following error:
Uncaught Error: addComponentAsRefTo(...): Only a ReactOwner can have
refs. You might be adding a ref to a component that was not created
inside a component's render method, or you have multiple copies of
React loaded
Facebook's documentation does not help.
_new_item.js.jsx
var NewItem = React.createClass({
handleClick() {
var name = this.refs.name.value;
var description = this.refs.description.value;
console.log('The name value is ' + name + 'the description value is ' + description);
},
render() {
return (
<div>
<input ref='name' placeholder='Enter the name of the item' />
<input ref='description' placeholder='Enter a description' />
<button onClick={this.handleClick}>Submit</button>
</div>
);
}
});
_body.js.jsx
var Body = React.createClass({
render() {
return (
<div>
<NewItem />
<AllItems />
</div>
);
}
});
_main.js.jsx
var Main = React.createClass({
render() {
return (
<div>
<Header />
<Body />
</div>
);
}
});
I really don't know where the error is.
You'll better use the function refs instead of the named refs:
So instead of
<input ref='name' />
You can use:
<input ref={node => this.nameElement = node} />
And then instead of:
this.refs.name
Use
this.nameElement
I believe it will fix your problem.

React.js passing => in props

Follow up on this question but deserved a separate thread Trying to convert React.CreateClass to extends React.Component.
I'm wondering how I can make use of => while calling the component but without passing in the exact input name, that should get filled up by the component internally:
Component:
var FormFields = React.createClass({
render: function() {
const upwd = this.props.unamepwd;
return(
<form>
Username: <input value={upwd.username}
onChange={this.props.handleChange('username')} /><br />
Password: <input type="password" value={upwd.password}
onChange={this.props.handleChange('password')} />
<button onClick={this.props.updateChanges}>Go!</button>
</form>
);
}
});
While in the parent render method I would like to call it something like:
<FormFields unamepwd={this.state}
handleChange={() => self.handleChange()} updateChanges={self.updateToServer} />
The following would work but only for the username field:
<FormFields unamepwd={this.state}
handleChange={() => self.handleChange('username')} updateChanges={self.updateToServer} />
Just pass an argument to the function.
<FormFields unamepwd={this.state}
handleChange={(fieldName) => self.handleChange(fieldName)} updateChanges={self.updateToServer} />
and call it like:
this.props.handleChange('password')
You can use e.target in the function handling onChange event to get a reference to the input that has triggered the event. So you only pass a reference to the handleChange function arround, no need for {x => handleChange('name') } or { handleChange.bind('name') } or whatever.
var FormFields = React.createClass({
render: function() {
const upwd = this.props.unamepwd;
return(
<form>
Username: <input value={upwd.username}
onChange={this.props.handleChange} name="username" /><br />
Password: <input type="password" value={upwd.password}
onChange={this.props.handleChange} name="password" />
<button onClick={this.props.updateChanges}>Go!</button>
</form>
);
}
});
var Parent = React.createClass({
handleChange(e){
console.log( e.target.name );
},
render(){
return <FormFields handleChange={ this.handleChange } />
}
});
http://jsfiddle.net/mg5cbepk/

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