I have an input with the disabled boolean propagated from the props. I've found that with that disabled variable being set, even when it's true I cannot type into the input. I can, however, type into the input if I hold the mouse down on it and keep it down as I type.
This happens when I render the component as both controlled and uncontrolled.
The only way to fix it is to either removing disabled or setting disabled={false} -- but I need it to be variabled.
This is my input:
class DashboardWidgetTitle extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.state.title = props.widget.getTitle();
}
render () {
return <input className="title"
value={this.state.title}
disabled={!this.props.isEditMode}
onChange={this._onInputChange.bind(this)}/>
}
_onInputChange(e) {
logit("input change");
this.setState({title: e.target.value});
}
}
Thanks!
EDIT: Extra info --
This is used in a widget within an implementation of ReactGridLayout.
The component is rendered by a widget that is rendered by the implementation of react grid layout, the "dashboard". That Dashboard has isEditMode as a state that's changed externally via a toggle in Angular (we use React within Angular).
If I switch tabs and come back, the focus remains. Otherwise whenever I type a letter, the input becomes unfocused.
The input isn't disabled when it shouldn't be, it just has focusing issues -- however removing the disabled attribute or setting it as a static variable, the issue doesn't remain.
When I switch the disabled toggle to be isEditMode rather than !isEditMode, everything works. It seems to be there's an onclick on the draggable/resizable portion of the ReactGridLayout that's causing some issues.
My issue was described right here: https://github.com/STRML/react-grid-layout/issues/615
My own fault of poor research.
Related
i defined multiple state for my app like this:
const
[state,setstate]=React.useState({headerpic:'',Headerfontfamily:'',Subheaderfontfamilty:''})
and i use a input as follows for getting an image from my device:
<Button variant='contained' color='primary' className={styler.buttons} name='headerpic'
>Header Pic
<input type='file' value={state.headerpic } style=
{{width:'100%',height:'auto',opacity:'0',position:'absolute',top:'0px'}} onChange=
{(e)=>fileuploader(e)}></input>
</Button>
i defined fileuploader like below:
const fileuploader=()=>{
if (e.target.files && e.target.files[0]) {
let img = e.target.files[0];
console.log(URL.createObjectURL(img))
setstate({
headerpic: URL.createObjectURL(img)
});
} }
when i click on button and choose the desired pic i got below error:
A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info:
any idea for solving this problem?
An input component that gets changed from controlled to uncontrolled generally means that your <input> goes from having a value to being undefined/null. This is most likely happening when an img gets removed in your case. The easiest fix would be to add a guaranteed value to your input field incase your state is undefined.
<input type='file' value={state.headerpic || ''} ... />
Does this resolve your issue?
It would be good if you let us know what it is you're exactly trying to do :/ and also some fuller code (the code given above, doesn't work!!)
If you're trying to make a file uploader I would recommend googling something like
"How to make file upload with react hooks"
Here's one I found earlier ;)
https://www.educative.io/edpresso/file-upload-in-react
which has a nice simple example of creating a file input and saving it in state with react hooks.
Inside of my React application, I have the following JSX code:
import React, { Component } from 'react'
export default class CategoryForm extends Component {
render() {
return (
<div className="category-form">
<label>
Category
<select value={this.props.selectedCategory} id="selectedCategory" onChange={this.props.handleChange}>
<option value="Best">Best</option>
<option value="Controversial">Controversial</option>
<option value="Hot">Hot</option>
<option value="New">New</option>
<option value="Rising">Rising</option>
<option value="Top">Top</option>
</select>
</label>
</div>
)
}
}
It's a simple element with elements as children. The default value is initialized as, "Best". When the page is initially visited or refreshed, the value contained in the element reverts to "Best" (as expected), but when a user navigates away from the page and presses the back button, the element retains whatever value was previously selected. How do I prevent this behavior? I'm trying to avoid forcing a re-render.
EDIT: I made the mistake of omitting code because I thought it would make the question more simple. Here's the state that I'm initializing in the constructor of the component, as well as the child component being created in the parent component. I modified my code according to the React documentation (and HMR) on controlled components, and I am still having the same problem.
export default class App extends Component {
constructor(props) {
super(props)
this.state= {
selectedCategory: "Best",
minScore: -100,
numPosts: 25,
subreddit: "",
searchTerm: "",
timeframe: "hour",
postArray: [],
animationTracker: false,
selectedForm: "Category",
}
this.handleChange = this.handleChange.bind(this);
this.backendCall = this.backendCall.bind(this);
this.changeForm = this.changeForm.bind(this);
}
\\ handle change method
handleChange(event) {
// dynamically set the key of the setstate object to be equal to the id of the specific form
let selectedCategory = event.target.id;
this.setState({[selectedCategory]: event.target.value});
}
\\ later on...
{this.state.selectedForm === "Category"
? <CategoryForm selectedCategory={this.state.selectedCategory} handleChange={this.handleChange.bind(this)}/>
: <TermForm handleChange={this.handleChange.bind(this)}
searchTerm={this.state.searchTerm} timeframe={this.state.timeframe} />
}
ScreenshotHere is a screenshot showing the problem in action. After pressing the to back button, the state is reinitialized (which should change the value to "Best"), but the value of my element remains at whatever the user selected before navigating away from the page (in this case, "Hot"). In addition, if I modify the fields below (Minimum score and number of posts), then navigate away from the page, then press the back button, those fields follow the expected behavior and revert to the default state.
We might need to see more of your code.
I'm guessing that the handlechange() function sets the local state to the selected option. You'll need to clear that state to revert to the default option.
Is there any way (please provide an example) in React / React Native to have a component render a timer with milliseconds, a submit button, and a text input field where the following conditions are met?
The user can type in the input field and see what he is typing.
No event handlers are assigned to the input field
When the submit button is clicked the program displays an alert() with the text typed by the user.
The component has an initial state value that is initially displayed in the input field.
The user does not experience unexpected behaviors while typing.
A previous question about this subject lead me to this more specific question about the matter (I hope you can see how it is related).
The most commonly accepted pattern in React to implement input fields suggest to always use an onChange event (see the docs), but I think this leads to repetition and noise in the code, so I´m looking for a better pattern where the developer doesn´t have to think about the onChange behavior when all he needs is an input form field.
Extra Note 1: An "state value" is a value in the component's state. i.e. "constructor(){ this.state = {value:'Initial Value'} };".
Extra Note 2: The purpose of the timer is to make sure you're triggering a render() periodically, which makes it a challenge to display the initial "state value", and allow the user to type normally without an onChange handler to update the state accordingly.
What are you looking for is called Uncontrolled Components.
Take a look here: https://reactjs.org/docs/uncontrolled-components.html
Your conditions will be met with this refs-based pattern ?
class App extends React.Component {
constructor(props) {
super(props);
this.textInput = null;
}
handleSubmit = () => alert(this.textInput.getDOMNode().value);
render() {
return (
<div>
<textarea
ref={el => this.textInput = el}
>
My initial value
</textarea>
<button onClick={this.handleSubmit}type="button">Submit</button>
</div>
);
}
}
React.render(<App />, document.getElementById('app'));
<div id="app"></div>
Working codepen: https://codepen.io/anon/pen/roypOx
Because conditions are about only input field and not timers I've not included a timer in the example.
Let's I have a form where I allow the user to fill in and choose some options.
It might look like
<MyForm>
<InputWithValidation />
</MyForm>
The component <InputWithValidation /> performs some validation, say their username has to be a certain length, before this submission can go through.
Right now the way I have this set-up is MyForm has a function, submit() which I pass as a prop to my InputWithValidation. On clicking submit, InputWithValidation checks its input, and if its valid, will call this.props.submit. It is working fine. However, now I want to add a hotkey to submit the form, so I add the following to MyForm:
document.onkeyup = function (event) {
if (/* keys match what I want */) {
this.submit();
}
}
However, this won't work, as I've never called the validation on the input. How do I solve this issue for 1 input, and for many inputs? While this is similar to form validation I think the hotkey adds a little more complexity.
I feel my question is similar to this question Validate the child's component data in parent component but I am hoping for someone to answer with some sort of best practices for a situation such as this.
Thank you for any help!
Since your <InputWithValidation /> class already has access to the appropriate context of this.props.submit(), I recommend moving that event handler to your <InputWithValidation /> class. You can add it after component mount like this.
class InputWithValidation extends React.Component {
//constructor
//other functions
componentDidMount() {
//add keydown event handler here
//pass to parent with this.props.submit(e.whatever)
}
render() {
//render function
}
}
I'm learning to Think in React, but don't understand why the SearchBar in the example needs to have value={this.props.filterText} and checked={this.props.inStockOnly}, the jsFiddle still works without them and it doesn't make sense for props to be passed to the SearchBar as the Search is the one handling user input and making changes to the state. The user input will be reflected in the value of the input without it being set to this.props.filterText so why is it there?
var SearchBar = React.createClass({
handleChange: function() {
this.props.onUserInput(
this.refs.filterTextInput.value,
this.refs.inStockOnlyInput.checked
);
},
render: function() {
return (
<form>
<input
type="text"
placeholder="Search..."
value={this.props.filterText}
ref="filterTextInput"
onChange={this.handleChange}
/>
<p>
<input
type="checkbox"
checked={this.props.inStockOnly}
ref="inStockOnlyInput"
onChange={this.handleChange}
/>
{' '}
Only show products in stock
</p>
</form>
);
}
});
React has concept of controlled components. A controlled component means its value is set by state (And not the other way around i.e. State being set by value of component).
Consider the following example:
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = {term : ''};
}
render() {
return (
<div>
<input value={this.state.term} onChange = {event => this.setState({term : event.target.value}) }/>
</div>
);
}
}
In above example <SearchBar /> is a Controlled Component.
Following will be sequence of events:
You type 'abc' in input field.
At this time value of input field does not change. Rather the State of component is changing because of our code in onChange Event.
As the state of component changes, the component is rendered again. And now the value of component becomes 'abc'.
This concept becomes more important when we use redux, Actions etc.
Because you will be needing the inputted value from the search bar to the upper component. For instance, if you need to filter a collection based on the given value (through search bar), then the filtering will happen on the upper component, not on the search bar. Search bar is only for the input. We put the value of the search bar from the props to make sure that the values are aligned.
The example here depicts the use of controlled input from the parent component. As you see
<input
type="text"
placeholder="Search..."
value={this.props.filterText}
ref="filterTextInput"
onChange={this.handleChange}
/>
Here the value of input box is set to {this.props.value} and in the handlechange function you are the onUserInput function which you check is again passed as a prop to the Searchbar. This calls the handleUserInput function ni the FilterableProductTable component and it sets the states filterText, inStockOnly and only these are passed as props to the Searchbar component. So although you can do without it, but controlled input is the way to go in most cases since we are accepting the value provided by the user and updating the value prop of the <input> component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. i.e. if you want to validate an input field or put restrictions on the input value its easier to do with controlled input