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}
Related
I have this piece of code.
Where the problem I am facing is that is missing a prop which I want to be an id, obtained inside the map function.
Since I am unable to find a way to send the id to the component outside map, I figured I would do this:
This is my render function
render() {
var users = this.state.userList;
const Table = Reactable.Table,
Td = Reactable.Td,
Tr = Reactable.Tr;
if (users.length === 0) {
return <p>loading</p>
}
return (
<div class="maincontainer">
<div className="content-landing">
<Table
className="table"
filterable={['Email']}
itemsPerPage={8}
currentPage={0}
sortable={true}
>
{users.map((row) => {
return (
<Tr className={row.className}>
<Td column="Email">{row.email}</Td>
<Td column="Edit" ><FontAwesomeIcon className="editIcon" onClick={this.showModal(row.id)} icon={faEdit} /></Td> //----THIS.SHOWMODAL IS BEING AUTOEXECUTED WITHOUT ACCOUNTING FOR THE CLICKING
</Tr>
)
})}
</Table>
<EditUserModal show={this.state.showModal} close={this.closeModal} row={this.state.rowId}/> //---I WANT THIS TO RECEIVE A row.id FROM THE ABOVE MAP
</div>
</div>
)
}
I have written a couple comments in the parts where I want to make the changes.
I also thought about putting <EditUserModal> , inside the <Td> , but since its an external npm module it crashes, it only admits text.
So my solution was, to pass the row.id to the showModal function, and try to set is a state from there.
showModal(rowId) {
// console.log("showmodal state before any click")
// console.log(this.state.showModal)
console.log("triggered show modal")
console.log(rowId)
this.setState({
showModal: true,
rowId: rowId
}, () => {
// console.log("clicked show modal")
// console.log(this.state.showModal)
});
}
I think it should work, but since the function has a () , it auto executes without waiting for any click, making my app to crash.
In your code you are executing the function directly: this.showModal(row.id).
You have to use a callBack function to pass row.id something like:
onClick={()=> this.showModal(row.id)}
This should solve your problem.
You can use a callBack function in the onClick like this:
onClick={()=> this.showModal(row.id)}
Or you can define the showModal function like this:
showModal = (rowId) => () => {
...
}
and onClick={this.showModal(row.id)}
For people who does not understand arrow functions, the above solution is similar to this:
function showModal(rowId) {
return function () {
...
}
}
The showModal function returns another function that will be triggered in the onClick event.
I have a parent component which looks like the following
UploadView.js
getInitialState: function () {
return {
file: null,
mappingType: null
}
},
setMappingType: function(){
this.setState({
mappingType: this.state.mappingType
});
},
render: function(){
<FileDropdown mappingType={this.setMappingType}/>
<FileUpload mappingType={this.state.mappingType}/>
}
FileDropDown is a child component that presents the user with a dropdown feature and looks as the following
FileDropDown.js
pickedOption: function(event){
var option = event.nativeEvent.target.selectedIndex;
var value = event.nativeEvent.target[option].text;
this.props.mappingType = value;
},
render: function(){
return (
<select name="typeoptions" id="mappingTypes" onChange={this.pickedOption}>.....</select>
)
}
I am trying to understand, if the above the right way to update the state and will updating/setting the value this.props.mappinType in FileDropDown will set the updated value to the state mappingType in the parent UploadView
If I understand it correctly, you send a function (or method) called setMappingType from UploadView.js to FileDropDown.js. When picking an option in FileDropDown.js at the method pickedOption you will call this function, causing the parent component to update.
Instead of doing that, you actually assigned the value to the props. In other words, change this
this.props.mappingType = value;
into
this.props.mappingType(value);
Then change the method setMappingType to a function which actually receives this value
setMappingType: function(value){
this.setState({
mappingType: value
});
},
Oh and something else, unrelated to your question, you can retrieve your value using refs like so:
pickedOption: function(event){
var value = this.refs._myRef.value;
},
render: function(){
return (
<select ref='_myRef' onChange={this.pickedOption}>
<option value='1'>One</option>
<option value='2'>Two</option>
</select>
)
}
I hope it helps ;)
Short answer, no, it won't work this way.
You need to change your setMappingType function to:
setMappingType: function(value){
this.setState({
mappingType: value
});
},
As you currently have it, it will just always be set to null because you are setting the state variable mappingType to the value of the state variable mappingType which is initially null. So it will just stay that way.
The proper way to pass the value to the parent function is like this:
pickedOption: function(event){
var option = event.nativeEvent.target.selectedIndex;
var value = event.nativeEvent.target[option].text;
this.props.mappingType(value);
},
Assigning it as you have, won't work.
I''ll admit I'm not an expert in React, but to my understanding this is how things need to be done. Hope this helps.
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.
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);
}
Though i have included the onclick handler for the a tag in the html returned by the render method of the reactjs component(component with the name renderLocationLink) , though the rendering takes place correctly the onclick handler attribute doesnt appear in the rendered html on the webpage .I want the Not able to figure whats the issue , here is the code
var feedApp = React.createClass({
getInitialState: function(){
return {
data : [
{display_name:"Rao",content:"this is Rao post",links:['link1','link2','link3']},
{display_name:"Sultan",content:"this is Sultans",links:['link4','link5','link6']},
{display_name:"John",content:"this is John post",links:['link7','link8','link9']}
]
}
},
fetchFeedsFromUrl: function(){
console.log('Onclick triggered');
},
render: function(){
return (<Feeds data={this.state.data} onClick={this.fetchFeedsFromUrl} />)
}
})
var Feeds = React.createClass({
render: function(){
var onClickfunc = this.props.onClick;
var feeds = this.props.data.map(function(feed){
return (
<oneFeed name={feed.display_name} onClick={this.onClickfunc} content={feed.content} links={feed.links} />
)
});
return(
<div> {feeds} </div>
)
}
})
var oneFeed = React.createClass({
render: function() {
return (
<div>
<h3>{this.props.name}</h3>
<renderLocationLink onClick={this.props.onClick} linkArray={this.props.links} />
<p>{this.props.content} </p>
</div>
)
}
});
var renderLocationLink = React.createClass({
render: function(){
var onClick = this.props.onClick;
var locationLinks = this.props.linkArray.map(function(link,index){
return (<a onClick={this.onClick} href={link}>{link} </a>)
})
return ( <div >{locationLinks}</div> )
}
})
React.renderComponent(feedApp(null),document.body);
You do not need to reference "this" in your map functions to access your local variable. Remove "this" when you try to access the onClick variable.
var renderLocationLink = React.createClass({
render: function(){
var onClick = this.props.onClick;
var locationLinks = this.props.linkArray.map(function(link,index){
return (<a onClick={onClick} href={link}>{link} </a>)
})
return ( <div >{locationLinks}</div> )
}
})
Your rendered markup will not contain an onClick attribute. What you write in your JSX markup is not a direct HTML markup.
What will happen instead is that React will give your markup a data-reactid attribute, and will make sure its own event handlers fire something when a specific data-reactid gets clicked.
Ok, so I have found out where it goes wrong:
In many components you were using this incorrectly. You were using this within the render function. So instead of using
{this.onClick} you should have been using {onClick} instead.
Look at this example, how we use {onClick} (and not {this.onClick}) in the returned render.
var Feeds = React.createClass({
render: function(){
var onClickfunc = this.props.onClick;
var feeds = this.props.data.map(function(feed){
return (
<oneFeed name={feed.display_name} onClick={onClickfunc} content={feed.content} links={feed.links} />
)
});
return(
<div> {feeds} </div>
)
}
})
Here's a working JSFiddle: http://jsfiddle.net/kb3gN/6771/
PS: This is exactly as Butters suggested.