5

I'm trying to submit a simple form to my Rails app. I lost myself in confusion and nothing's working. This is what I have tried to do:

var newUserForm = React.createClass({
  propTypes: {
    user: React.PropTypes.array
  },
  getInitialState: function() {
    return {name: '', age: '', country: '' };
  },
  handleNameChange: function(e) {
    this.setState({ name: e.target.value });
  },
  handleAgeChange: function(e) {
    this.setState({ age: e.target.value });
  },
  handleCountryChange: function(e) {
    this.setState({ country: e.target.value });
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var name = this.state.name.trim();
    var age = this.state.age.trim();
    var country = this.state.country.trim();
    if (!name || !age || !country) {
      return;
    }
    this.setState({ name: '', age: '', country: '' });

    var user = {user: this.state.user}
    this.setState({data: user});
    $.ajax({
      url: '/users/new',
      dataType: 'json',
      type: 'POST',
      data: {user: user},
      success: function(data) {
        this.setState({data: user});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: user});
       console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },


  render: function() {
    return (
      <form onSubmit={ this.handleSubmit }>
        <input type="text" placeholder="User's name" value={ this.state.name } onChange={ this.handleNameChange } />
        <input type="text" placeholder="His age" value={ this.state.age } onChange={ this.handleAgeChange } />
        <input type="text" placeholder="Country of origin" value={ this.state.country } onChange={ this.handleCountryChange } />

        <input type="submit" value="Post"/>
      </form>
    )
  }
});

And my console: enter image description here

I need some help.

toy_controller.rb

class ToyController < ApplicationController
  def index
    @users = User.all
    render component: 'usersList', props: { users: @users }
  end

  def new
    @user = User.new
    render component: 'newUserForm'
  end

  def create
    @user = User.new(user_params)

    if @user.save
      render component: 'showUser', props: {user: @user }
    else
      render text: "Something went wrong."
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :age, :country)
  end
end

routes.rb

Rails.application.routes.draw do
  get '/users', to: 'toy#index'
  get '/users/new', to: 'toy#new'
  post '/users/new', to: 'toy#create'
end
4
  • Are you using server side rendering for React? Where are you mounting the component? The error is saying that you're rendering into an element that already has markup, and it doesn't match the markup that React generated when running render the first time. Rendering into an empty element like <div></div> will prevent this error. Commented Jul 21, 2016 at 21:39
  • You have both user and users variables, what is the expected values of these? Commented Jul 22, 2016 at 11:47
  • 1
    I haven't used Rails in a decade, but shouldn't you include the user object in a property called 'user' in order to send it as JSON? (i.e. data: { user: user },) Commented Jul 22, 2016 at 13:33
  • Can you please post your log (placed in log/development.log)? Because we don't know what's causing BadRequest in Rails. Commented Jul 28, 2016 at 8:19

1 Answer 1

4
+25

TL;DR: you most likely just need to restructure the JSON you are sending to include the 'user' key


lengthier response:

you are using what are called 'strong params', so when you call user_params in #create and have require(:user), if the params hash does not have the word user as a key, the error you see above is raised.

one route would be to restructure the data you are sending to include the word 'user'

for instance:

{user: {name: 'test', age: 1}}

so maybe (could modify however you'd like to achieve the above structure)

$.ajax({
  url: '/users/new',
  dataType: 'json',
  type: 'POST',
  data: user,
  success: function(data) {
    this.setState({data: user});
  }.bind(this),
  error: function(xhr, status, err) {
    //this.setState({data: user});
    // console.error(this.props.url, status, err.toString());
  }.bind(this)
});

to

$.ajax({
  url: '/users/new',
  dataType: 'json',
  type: 'POST',
  data: {user: user},
  success: function(data) {
    this.setState({data: user});
  }.bind(this),
  error: function(xhr, status, err) {
    //this.setState({data: user});
    // console.error(this.props.url, status, err.toString());
  }.bind(this)
});
Sign up to request clarification or add additional context in comments.

13 Comments

@siaw23 wanna try out what I had written and see what happens?
Specifically var user = this.state.user; should likely be var user = {user: this.state.user};. I'd also then change the name to userData as it's more indicative of what's inside it.
i'm updated my post as per your suggestion. you can see the new error in the console. also i'm not sure if the routes.rb file makes any sense.
@siaw23, thank you! before you send the JSON client-side could you print it out and tell me what the response is? i.e. console.log(user)
@siaw23 also, typically to create a resource, the url would be '/resource' in your case and using POST as opposed to get (as you had done), but of course feel free to map the urls however you'd like my good sir!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.