What is the purpose of passing props to a React search bar? - javascript

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

Related

React Redux - Display string stored in Redux state within Input field

I have an input field that the user types into. This Input field looks like this:
// within React component render function:
...
<input
id="autoComplete"
className={inputClasses}
type="text"
// used to display user typed words in input field
ref={this.inputRef}
// onchange is used to store value in redux store
onChange={this.inputChangeHandler}
/>
In the above code, the 'ref' is for displaying the user typed letter in the input field. However, I also have Google Maps Autocomplete integrated into this input field. The Autocomplete feature works fine & when the user clicks on one of the autocomplete results, the input field is populated by that name & onChange handler stores the value within the redux store.
So far, so good. However, now, when the user navigates to another section of the site, how do I populate the input field with the value within the redux store. There is no 'value' attribute on the input field, & its using React's ref method.
Thank you
You can change/add value to input element using ref. ref will basically have the reference of actual dom node, so by changing this.refName.current.value will change the input value.
But you need to do it after initial rending, means after ref get the reference of input element.
Check this working example:
class App extends React.Component {
constructor() {
super();
this.a = React.createRef();
}
click = () => {
this.a.current.value = Math.floor(Math.random()*100);
}
render() {
return (
<div>
<input ref={this.a} placeholder="Number" />
<button onClick={this.click}>Click here to change the input value</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='app' />

React text form fields without onChange

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.

Updating state in Reactjs?

I am trying to update my state in ReactJS. To do this I have an input field in a Reactjs class. The field is automatically filled in with data from a parent class. The field looks like this:
<input
onChange={e => this.props.store.addLego(e)}
name="piece"
value={this.props.row.original.piece}
/>
The addLego function is designed to update my state and is in a MobX store. It looks like this:
addLego = action("addLego", e => {
this[e.target.name] = e.target.value;
});
However, I can't actually edit the input field! Nothing changes in the field when I type! Thanks for your help!
If you set a value attribute to an <input> field that field becomes a controlled input. This means that whatever gets passed to value is rendered on the screen. In your case, if you are not updating this.props.row.original.piece the <input> field will never get a new value. I'll suggest to read this bit of React's documentation https://reactjs.org/docs/forms.html#controlled-components
It is basically suggesting to keep the new value somewhere (in the component's state for example) and set it back as a value to the field.
Follow this tutorial here will solve your problem. It's a good read too for handling single or multiple inputs
Basically, you'll need a state in the constructor
this.state = {value: ''};
Event handler to set the value every onchange
handleChange(event) {
this.setState({value: event.target.value});
}
And the setup for input
<input type="text" value={this.state.value} onChange={this.handleChange} />

Why is the product search filter not working in the Thinking in React tutorial

I'm trying to learn ReactJs and started following the tutorial on the official documentation. For some reason, the search filter text box after step4 seems to be read only. It is not taking in any text I entered. What is the issue here?
Here is the link to the tutorial
- https://facebook.github.io/react/docs/thinking-in-react.html
It seems like there is some issue with the way SearchBar is rendered. But I can't figure out what it is.
var SearchBar = React.createClass({
render: function() {
return (
<form>
<input type="text" placeholder="Search..." value{this.props.filterText}/>
<p>
<input type="checkbox" checked={this.props.inStockOnly} />
{' '}
Only show products in stock
</p>
</form>
);
}
});
https://jsfiddle.net/reactjs/zafjbw1e/?utm_source=website&utm_medium=embed&utm_campaign=zafjbw1e
If you look at the step 5 they show you why that don't work. They to this with a function inside the onChange. Remember: React is all about one-way data flow down the component hierarchy. So the props you pass to your component are coming from the parent. If you read further they teach you how the flow work. ;)
Hope that can help ;)
PS that was read only cause the value props is an empty string ;) And because you don't push to the top new state you don't change it.
var FilterableProductTable = React.createClass({
getInitialState: function() {
return {
filterText: '', // HERE AM EMPTY AND YOU DONT PASS NEW STATE SO I STAY EMPTY
inStockOnly: false
};
},
render: function() {
return (
<div>
<SearchBar
filterText={this.state.filterText}
inStockOnly={this.state.inStockOnly}
/>
<ProductTable
products={this.props.products}
filterText={this.state.filterText}
inStockOnly={this.state.inStockOnly}
/>
</div>
);
}
});
<input> is a so-called controlled component .Put simply ,the value inside the input bar is controlled be value property of <input> element ,thus you can only change the value by setting the value property ,
try to change
value={this.props.filterText}
to
value={"aa"}
you will know what I mean.Just keep following the tutorial , everything should be fine

How to update the state of child component from parent?

I am just getting started with React and not able to figure this out.
<Select>
<Search term={this.state.filename} />
</Select>
Select component is for selecting a file, I want to set the initial value of input text inside the Search component to be the filename.
Here is the Search component
<form onSubmit={this.handleSubmit}>
<input
type="search"
value={this.props.term}
onChange={this.handleChange}
/>
</form>
Now, whenever user tries to change the value of input from the initial value set by the parent, I set the state of the child with the new input value but this triggers re-render of the child which resets the input value. What is the correct way around this?
What I am currently thinking is if I assign the value of input like this value={this.props.term}
, then changing the state will trigger re-render of the child with the filename as the default value and user will be able to edit it.
Try have onChange on Search be delegated to a props so that your parent will be the one that sets the value when onChange is called on child.
onChange={this.props.onInputChange}
Here you are using value={this.props.term}, which makes the input a controlled component. The value here will always be same as this.props.term, which is the state from parent component. <Search term={this.state.filename} />
I guess what you really want to do here is change parent's state inside child component.
Then you should pass a function from parent component to child component. The function will change the state of parent component. You should define Something in parent component like these:
onChildInputChange(term) {
this.setState({term: term })
}
Then pass it to child component through props
<Select>
<Search term={this.state.filename} onChildInputChange={this.onChildInputChange} />
</Select>
so that in child component you can do this:
<form onSubmit={this.handleSubmit}>
<input
type="search"
value={this.props.term}
onChange={()=>{this.props.onChildInputChange()}}
/>
</form>

Categories

Resources