G.D G.D - 2 months ago 15
React JSX Question

Issue with componentWillReceiveProps

void componentWillReceiveProps(
object nextProps
)


This is what official documentation says => Invoked when a component is receiving new props. This method is not called for the initial render.

I am rendering a component with props like below in the parent component -

<ArticleDetails articleDetails={this.state.details}></ArticleDetails>


ArticleDetails component has componentWillReceiveProps method defined. According to documentation it should not get called when I refresh the page(initial render), but it does. If the reason is because I am passing props on first call itself, then is there any way that you could render it first time without passing props and then somehow pass props later?

var ArticleDetails = React.createClass({
getInitialState: function() {
return {author: '', tags: '', data:'', relatedArticles:{}};
},
componentWillReceiveProps :function(){
console.log("i am called");
this.setState({tags:this.props.articleDetails._id||''})
},
handleSubmit: function(e) {
e.preventDefault();
/// do something
},
render: function() {
return (
<form className="articleForm" onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Your name"
value={this.state.heading}
/>
<input
type="text"
placeholder="Say something..."
value={this.state.tags}
/>
<input type="submit" value="Post" />
</form>
);
}
});

Answer

First, you're not using componentWillReceiveProps correctly. The method gets passed next props. Using this.props inside of that method will give you the previous props. E.g. (in pseudo code)

input field initial props = Hi 
input field update to props = Hi! 
nextProps = Hi!
this.props = Hi

I don't think you'll be too happy with your code structure long term. Using props to set state is considered an anti pattern. https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

Why not use the props directly?

<input
   type="text"
   placeholder="Say something..."
   value={this.props.tags}
 />

I would do it this way...

http://jsbin.com/sojaju/edit?js,output

var Article = React.createClass({
    getInitialState: function() {
        return { tags : 'Sports, Football'};
    },
    handleSubmit: function(e) {
        e.preventDefault();
        const { value } = e.target;
        this.setState({ tags: value });
        // send to server
    },
    handleTagChange(e) {
        const { value } = e.target;
        this.setState({ tags: value });
    },
    render: function() {
        return (
            <ArticleDetails 
                articleDetails={this.state.tags}
                handleSubmit={this.handleSubmit} 
                handleTagChange={this.handleTagChange}
            />
            );
    }
});

var ArticleDetails = React.createClass({

  render: function() {
        const { handleTagChange, articleDetails } = this.props;
    return (
      <form className="articleForm" onSubmit={this.props.handleSubmit}>
        <input
          type="text"
          placeholder="Say something..."
                    onChange={handleTagChange}
          value={articleDetails}
        />
        <input type="submit" value="Post" />
      </form>
    );
  }
});

ReactDOM.render(<Article />, document.getElementById('app'))