I just started learning React and I'm stuck in the following scenario.
There is an input field and on clicking the search button it takes the input value and redirect to /search/search-query/some-action
I have setup the path, defined the route to the correct view. And, I was able to do hit this path using href links. But my actual requirement is to have a button and take user to this path via onClick handler.
Searched a lot and found multiple (vague) solutions like, react-navigate-mixin etc. But I couldnt find any documentation around its usages.
Can anyone point me in the right direction?
I'm gonna make the assumption that you're not building a single page app and using something along the lines of React router. And that what you need to do is simply navigate to a url based on the input.
There are two main ways of doing depending on wether you want to:
Style an <a> as your button:
var Component = React.createClass({
getInitialState: function() { return {query: ''} },
queryChange: function(evt) {
this.setState({query: evt.target.value});
},
_buildLinkHref: function() {
return '/search/'+this.state.query+'/some-action';
},
render: function() {
return (
<div className="component-wrapper">
<input type="text" value={this.state.query} />
<a href={this._buildLinkHref()} className="button">
Search
</a>
</div>
);
}
});
This way you're keeping the query (value of the input) in the state. And whenever the input changes is automatically changes the href of the link.
Use a <button> and redirect programatically:
var Component = React.createClass({
getInitialState: function() { return {query: ''} },
queryChange: function(evt) {
this.setState({query: evt.target.value});
},
handleSearch: function() {
window.location = '/search/'+this.state.query+'/some-action';
},
render: function() {
return (
<div className="component-wrapper">
<input type="text" value={this.state.query} />
<button onClick={this.handleSearch()} className="button">
Search
</button>
</div>
);
}
});
This way you handle the redirect programatically by setting your desired location to window.location.
Adding on from the existing answer may need to bind your function like so:
constructor(props) {
super(props);
this.handleSearch = this.handleSearch.bind(this);
}
Related
Cant work out what is going wrong.
I click a button, this sets the state and the setting of state, changes a key to be true and if that key is true, a different output should be rendered. here is the code:
click button call function:
<input type="submit" value="I can play" onClick={() => this.canPlay()}/>
runs this function:
canPlay: function() {
let name = this.props.value;
console.log(name, 'name');
let email = 'mark#mail';
this.submitUserResponseCanPlay(this.today(), name, email)
this.setState({thanks: true}) //SET STATE HERE
},
(thanks is set to false in getInitialState)
then in the render function:
render: function(){
let output;
if (this.state.thanks){
output = <Thanks />;
}
if the state is true, then render the new output. the ` part is a class that just has a return part inside the render function that looks like:
var Thanks = React.createClass({
render: function(){
return (
<div id="results" className="search-results">
Thanks, your answer has been recorded!
</div>
)
}
});
This does not show up though. any idea why??
the stranger thing is it is like this in another part of my file, and that part works. i.e. i click a submit button earlier and that changes a key/value pair from false to true and renders a new page layout. just not working here. maybe ive missed something small..
render: function(){
let output;
if (this.state.thanks){
output = <Thanks />;
}
This should be
render: function(){
if (this.state.thanks){
return <Thanks />
}
You always have to return something inside the render
I dont think you can set variables as jsx so if im wrong ignore this. BUT in this case it seems like youre probably trying to render a
{output}
somewhere in your code. instead replace that with
{this.state.thank ? <Thanks /> : null}
I've got some confusion with React's event handler
I have a component like this, with handleChange handling onChange event:
var SearchBar = React.createClass({
getInitialState(){
return {word:''};
},
handleChange: function(event){
this.setState({word:event.target.value});
alert(this.state.word);
},
render: function () {
return (
<div style={{width:'100%',position:'0',backgroundColor:'darkOrange'}}>
<div className="header">
<h1>MOVIE</h1>
</div>
<div className="searchForm">
<input className="searchField" onChange={this.handleChange}
value={this.state.word} type="text" placeholder="Enter search term"/>
</div>
</div>
);
}
});
It does work, but not the way I expect. In textfield, when I type the first character, it alerts empty string, when the second character is typed, it alerts a string with only first character, and so on, with string length of n, it alerts the string with n-1 length
What did I do wrong here? How should I fix it?
Use like this,
Js:
this.setState({word:event.target.value}, function() {
alert(this.state.word)
});
Working Jsbin
I think it has something to do with state handling inside React.
I can come with two options to handle it.
Either:
handleChange: function(event) {
this.setState({word: event.target.value});
window.setTimeout(function() {
alert(this.state.word);
}.bind(this));
}
Or:
alertCurrentValue() {
alert(this.state.word);
},
render: function () {
this.alertCurrentValue();
return ( ... )
}
Praveen Raj's answer is definitely the right way to go. Here is the documentation I found from the official React website on why you should access this.state inside the callback rather than right after setState():
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.
Here's the render function for one of my react components:
render: function() {
var valueLink = this.linkState.value;
var handleBlur = function(e) {
valueLink.requestChange(e.target.value);
};
return (
<input
type="text"
defaultValue={valueLink}
onBlur={handleBlur}
/>
);
}
I'm using backbone-react. After setting an attribute on the model, this component calls its render function. The backbone model gets set properly, but the input field doesn't render the value that was set on the model.
Basically when the render function gets called after the valueLink.value changes, the input field doesn't reflect this change.
I've tried using value instead of defaultValue but that makes it a controlled component.
I also don't want to use valueLink as that sets state for every key press whereas I only what to trigger that for onBlur.
Any ideas? (Please let me know if you need more info.)
From React docs
LinkedStateMixin adds a method to your React component called
linkState(). linkState() returns a ReactLink object which contains
the current value of the React state and a callback to change it.
In your example, instead of this.linkState.value, pass a state variable to linkState. Ex this.linkState('message')
var Component = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function () {
var valueLink = this.linkState('message');
var handleBlur = function(e) {
valueLink.requestChange(e.target.value);
};
return (
<div>
<input
type="text"
defaultValue={valueLink.value}
onBlur={handleBlur}
/>
<br />
{this.state.message}
</div>
);
}
});
React.render(<Component />, document.body);
http://jsfiddle.net/kirana/ne3qamq7/12/
I am trying to implement Emberjs's Todo app as a practice exercise for Cortex by mquan on github. I am currently implementing the "All", "Active", "Completed" filter where clicking an anchor will result in the anchor being highlighted (class added).
I created the following:
var filtercortex = new cortex([
{title:'all', selected:true, key:1},
{title:'completed', selected:false, key:2},
{title:'active', selected:false, key:3}
]);
With the following render function (in the parent):
render: function() {
var filters = filterCortex.map(function(filter) {
return (
<li>
<FilterAnchor cortex={filterCortex} filter={filter} />
</li>
)
});
...
return ...
<ul id='filters'>
{filters}
</ul>
And FilterAnchor's definition:
var FilterAnchor = React.createClass({
handleClick: function() {
var that = this;
this.props.cortex.forEach(function(filter) {
if (filter.key.getValue() == that.props.filter.key.getValue()) {
console.log(filter.title.getValue(), true);
filter.selected.set(true);
} else {
console.log(filter.title.getValue(), false);
filter.selected.set(false);
}
});
return false;
},
render: function() {
var className = (this.props.filter.selected.getValue()) ? 'selected' : '';
return (
<a className={className} href="#" onClick={this.handleClick}>
{this.props.filter.title.getValue()}
</a>
)
}
});
right now, I do not see the class 'selected' being applied to the anchor links when I am clicking.
However, upon investigation I notice this:
Clicking "All":
All true
Completed false
Active false
Clicking "Completed":
All true
Completed false
Active false
So I am certain that the objects inside filtercortex has been updated properly (you can open up firebug to check). However, FilterAnchor.render is not being triggered.
Is this a bug?
Source code: https://github.com/vicngtor/ReactTodo/blob/cortex/script.jsx
The sample at the top of the Cortex readme has this at the bottom:
orderCortex.on("update", function(updatedOrder) {
orderComponent.setProps({order: updatedOrder});
});
Is there an equivalent section in your code? If not, then the problem is that the update event for the cortex data store isn't set to trigger an update of the view, which is made through a call to setProps on the top level React component in this example.
I have a problem with reload input value.
<input type="email" ref="email" id="email" value={this.props.handlingAgent.email}/>
after that i use
this.props.handlingAgent.email = "asd"
In debugger value of this.props.handlingAgent.email is actually asd, but in input is still old value. How to refresh that value without JQuery? Shouldn't it refresh automatically?
First, props are what's been passed onto you. View them as function parameters. The child really shouldn't go modify them since it breaks whatever assumption the parent has and makes your UI inconsistent.
Here, since the prop's passed onto you, you want to get a handler from parent that you can call to notify your change:
var App = React.createClass({
getInitialState: function() {
return {inputValue: ''};
},
handleChange: function(value) {
console.log('Value gotten back from the child: ' + value);
this.setState({
inputValue: value
});
},
render: function() {
return <Field onChange={this.handleChange} inputValue={this.state.inputValue} />;
}
});
var Field = React.createClass({
handleChange: function(event) {
// Make sure the parent passes the onChange to you as a prop
// See what I did here? It's not the actual DOM onChange. We're manually
// triggering it based on the real onChange fired by the `input`
this.props.onChange(event.target.value);
},
render: function() {
// I named the value prop `inputValue` to avoid confusion. But as you can
// see from `onChange`, it'd be nicer to name it just `value`
return <input value={this.props.inputValue} onChange={this.handleChange} />;
}
});
So yes, it does refresh "automatically", if you tell the parent to change. Instead of modifying what's been passed onto you, you use vanilla callbacks to the parent by passing it your new value. Then it flushes down the same value (or different, if fits) down to you.