I have a textarea
<textarea ref="newText" defaultValue={this.props.children}></textarea>
I need to fetch its value,I tried like this.
this.props.update(this.refs.newText.value,this.props.index);
I also used text instead of value but still it returns undefined.
this.refs.newText.value
Try updating your react-dom libraries. ref help you to imperatively modify a child without the need to use props.get the latest from react docs
src="https://unpkg.com/react#15/dist/react.js">
src="https://unpkg.com/react-dom#15/dist/react-dom.js">
Check out Refs & the DOM
It's hard to debug without the full source code of your component. I've prepared a codepen which shows two ways of accessing the value entered in the <textarea/> element: http://codepen.io/PiotrBerebecki/pen/amJAqb
Have a look also at the React Forms docs: https://facebook.github.io/react/docs/forms.html#controlled-components
const TextArea = React.createClass ({
getInitialState: function() {
return {
userInputValue: '',
userInputRefs: ''
};
},
handleChange: function(event) {
this.setState({
userInputValue: event.target.value
});
this.setState({
userInputRefs: this.refs.userData.value
});
},
render: function() {
return (
<div>
<textarea ref="userData"
type="text"
onChange={this.handleChange}
value={this.state.userInputValue} />
<h3>User input value:</h3>
<p>{this.state.userInputValue}</p>
<h3>User input refs:</h3>
<p>{this.state.userInputRefs}</p>
</div>
);
}
})
ReactDOM.render(
<TextArea />,
document.getElementById('app')
)
Related
I am a newbie in React and have got a problem using hook.
I am going to build a basic form as a child component, but I am wondering why input element on the child form is not rendered when changing its value.
Here is my code.
'use strict';
function SearchForm({form, handleSearchFormChange}) {
return (
<div className="card border-0 bg-transparent">
<div className="card-body p-0 pt-1">
<div className="form-row">
<div className="col-auto">
<label className="mr-1" htmlFor="number">Number:</label>
<input type="text" className="form-control form-control-sm w-auto d-inline-block"
name="number" id="number" value={form.number} onChange={handleSearchFormChange}/>
</div>
</div>
</div>
</div>
);
}
function App() {
const formDefault = {
number: 'Initial Value'
};
const [form, setForm] = React.useState(formDefault);
const handleSearchFormChange = (e) => {
setForm(Object.assign(form, {[e.target.name]: e.target.value}));
console.log('Handle Search Form Change', e.target.name, "=", e.target.value);
};
return (
<React.Fragment>
<div>Number : {form.number}</div>
<SearchForm form={form} handleSearchFormChange={handleSearchFormChange} />
</React.Fragment>
);
}
const domContainer = document.querySelector('#root');
ReactDOM.render((
<React.Fragment>
<App/>
</React.Fragment>
), domContainer);
I defined an onChange event handler for 'number' element in parent component and tried to transfer the value to child component using props.
The problem is that when I am going to change 'number', 'number' input element is not changed at all. (Not rendered at all). So that input element has always 'Initial Value'.
Could you advise on this?
And I'd like to know if this approach is reasonable or not.
Thanks in advance.
One of the philosophies of react is that state is immutable. Ie, you don't change properties of the existing state object, but instead you create a new state object. This allows react to tell that the state changed by a simple === check from before and after.
This line of code mutates the existing form object, then passes that into setForm:
setForm(Object.assign(form, {[e.target.name]: e.target.value}));
So react compares the object before setForm and after, and sees that they're the same object. Therefore it concludes that nothing changed, and so the component does not rerender.
Instead, you need to make a copy of the object and make your changes on the copy. If you're used to Object.assign, that can be accomplished by putting an empty object as the first argument to Object.assign:
setForm(Object.assign({}, form, {[e.target.name]: e.target.value}));
Alternatively, the spread syntax is a convenient way to make a shallow copy of an object:
setForm({
...form,
[e.target.name]: e.target.value
})
Try replacing setForm(Object.assign(form, {[e.target.name]: e.target.value})); with
setForm(prevState => ({
...prevstate,
[e.target.name]: e.target.value
}));
So, I am using antd to handle a Form component that has an initial state like this:
...constructor
...super
state = {
tags: ["tag"]
}
handleSubmit = e => {
e.preventDefault();
console.log(this.state);
// gives me Object { tags: [] }
}
render() {
return <Form onSubmit={this.handleSubmit} />
}
This is literally it... but I have no idea why I keep getting an empty array in console. Maybe this is impossible to figure out with this much info, but that's why it's driving me insane. I have noticed that if I comment out some code in this class, that it will all of sudden start showing the array values... no idea.
Any help would be appreciated.
When I go into the React Devtools, it shows the "tag" in my tags array. But, when I hit submit, it clears the array. I'm guessing this is tied in somehow, but I'm not sure why the state is clearing just the tags array and not the other state values. Something to do with a deep clone... ?
For setup default values in ant design form and after validate you need to follow the required steps:
Wrap form:
class YouComponent extends Component { //..... }
const WrappedComponent = Form.create({ name: 'you_form' })(YouComponent);
export default WrappedComponent;
To setup default values:
in you case i think you can use the Select component for tags
<Form layout="inline" onSubmit={this.handleSubmit}>
<Form.Item>
{getFieldDecorator("tags", {
rules: [{ required: true, message: "Pleases select tag!" }]
})(
<Select
mode="multiple"
style={{ width: "100%" }}
placeholder="Please select"
// here setup default selected of tags
defaultValue={this.state.tags}
>
{// map here tags <Select.Option>}
</Select>
)}
</Form.Item>
</Form>
Select documentation
To validate and get value from form:
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log("Received values of form: ", values);
}
});
};
I developed a React App using Material-UI then I tried to create independent Components,
check the below independent components(<PanelDiv/>),
render() {
return (
<div className="panelDiv-component" style={{display:this.props.display}}>
<div className="panel-field-content">
<TextField
floatingLabelText={this.props.heading}
type={this.props.inputType}
value={this.props.value}
/>
{/* <input defaultValue className="form-control"></input>*/}
</div>
</div>
);
}
I tried to use the component like this,
<PanelDiv
heading='name'
inputType="text"
value={this.state.userData.name}
display={this.state.display[0]}
/>
But I can't update input field in this way.Also there is no error. How can i solve this? I want to update my input field.
Please check my input filed in the below image :
Because you are controlling the value of TextField by using value attribute but you are not updating the value by using onChange function, Since value of TextField is not changing so it becomes read only.
Solution:
Specify the onChange function with TextField and update the value inside that, Like this:
<TextField
floatingLabelText={this.props.heading}
type={this.props.inputType}
value={this.props.value}
onChange={this.props._change}
/>
Inside parent component:
_Change(event, value){
//update the value here
}
<PanelDiv
heading='name'
inputType="text"
value={this.state.userData.name}
_change={this._change}
display={this.state.display[0]}
/>
If you pass value as a prop to TextField you can't change that text!
On Material-UI official documentation they have used defaultValue="default val" as a prop.
So I used defaultValue as a prop! It worked fine for me!
<TextField
type="text"
defaultValue={this.props.val}
onChange={handleChange}
/>
Had the same error. I was not able to key in anything and it was because there was no name props included. example:
<TextField
type="email"
name='email'/>
Look at this example - https://jsfiddle.net/y857yeLq/
You should define a function, which is handles of text change and pass it to onChange property. In this example I used state for storing current text field value. I see, that you use props for that, but the principle is the same - function should update props in your case.
const { TextField, MuiThemeProvider, getMuiTheme } = MaterialUI;
class SliderExampleControlled extends React.Component {
state = {
value: '',
}
render() {
console.log(this.state);
return (
<div style={{width: '50%', margin: '0 auto'}}>
<TextField
hintText="Type here"
value={this.state.value}
onChange={(e) => this.setState(e.target.value)}
/>
</div>
);
}
}
const App = () => (
<MuiThemeProvider muiTheme={getMuiTheme()}>
<SliderExampleControlled />
</MuiThemeProvider>
);
ReactDOM.render(
<App />,
document.getElementById('container')
);
I was running into this problem as well and I needed the onClick function to take more than just the event I also needed it to take the row number because my state had an array representing the rows in a table. I was able to do that using this chunk of code
onChange={(e) => this.nameChange(e.target.value, row.row_num)}
then in my function called nameChange I was able to update the value
I am new to reactjs and trying to print update value of input field. What I firstly tried was this:
var App = React.createClass({
render() {
return <div>
<h1>Hello, {this.props.name}</h1>
<input type="text" onKeyUp={this.handleChange} />
<p>{this.handleChange}</p>
</div>;
},
handleChange: function(event) {
return event.target.value;
}
});
App = React.createFactory(App);
React.render(
<App name="World" />,
document.getElementById('mount-point'));
But I don't get it why it is not working. Than I tried this: CodePen maybe someone can help me with printing instantly the value of the input field in the <p> element
var App = React.createClass({
getInitialState: function() {
return {
text: "",
};
},
handleChange: function(event) {
this.setState({ text: event.target.value });
},
render() {
return <div>
<h1>Hello, {this.props.name}</h1>
<input type="text" onChange={this.handleChange} />
<p>{this.state.text}</p>
</div>;
},
});
You must store all state of the component in this.state. Use this.setState to update the state. When you update the state, the component is automatically rerendered with the new state.
The content of the paragraph is the current value of the state. onChange is commonly used instead of onKeyUp to handle changes of state in text inputs. handleChange will update the state when the text input changes.
I'm new to React and I've been facing a problem since few hours now. Even if I found some topics on Stackoverflow or Google that seems equivalent to my issue, I'm unable to solve it...
I'm using react-select to create a simple form. For now, I have only one multi-select input. I am able to use it as expected but when I press "Submit" I want to retrieve the values selected. I tried with refs, with onChange without success. onChange is never fired, that might be an other issue as well.
var MultiSelect = React.createClass({
onLabelClick: function (data, event) {
console.log(data, event);
},
render: function() {
var ops = []
this.props.categories.forEach(function(category) {
ops.push({ label: category.name, value: category.id });
});
return (
<div>
<Select
name = {this.props.name}
delimiter=" "
multi={true}
allowCreate={true}
placeholder = {this.props.label}
options={ops} />
</div>
);
}
});
var ProductForm = React.createClass({
submit: function () {
console.log("Categories: " + this.state.categories);
},
onCategoryChange: function(e) {
console.log("CATEGORY CHANGED !!!!!!")
this.setState({categories: e.target.value});
},
render: function () {
return (
<form onSubmit={this.submit}>
<MultiSelect label="Choose a Category" name="categories" categories={this.props.categories} onChange={this.onCategoryChange}/>
<button type="submit">Submit</button>
</form>
);
}
});
PS : data categories comes from a Rails controller.
I believe your internal Select component should receive onChange from the props provided to MultiSelect, assuming your intention is to listen to changes on the Select component.
Try something like this inside your MultiSelect's render() method:
return (
<div>
<Select
name = {this.props.name}
delimiter=" "
multi={true}
allowCreate={true}
placeholder = {this.props.label}
options={ops}
onChange={this.props.onChange} />
</div>
);
Side note, I don't think e.target.value is going to work inside onCategoryChange, since react-select doesn't send standard events.