I'm trying to use react_on_rails
to build my first example with react and rails. I'm trying to save some data to the rails backend, using axios for the ajax.
here's my code:
import store from "../store/helloWorld";
import axios from "axios";
export const SAVE_NAME = "SAVE_NAME";
export function saveNameAction(name) {
return {
type: SAVE_NAME,
name
};
}
export function saveName(name) {
axios
.post("/hello_world", saveNameAction(name))
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
}
and the component:
import PropTypes from "prop-types";
import React from "react";
import * as actions from "../actions/helloWorld";
export default class HelloWorld extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired // this is passed from the Rails view
};
/**
* @param props - Comes from your rails view.
*/
constructor(props) {
super(props);
this.state = { name: this.props.name };
}
updateName(name) {
this.setState({ name: name });
}
handleSubmit(event) {
event.preventDefault();
actions.saveName(this.state.name);
}
render() {
return (
<div>
<h3>
Hellopp, {this.state.name}!
</h3>
<hr />
<form>
<label htmlFor="name">Say hello to:</label>
<input
id="name"
type="text"
value={this.state.name}
onChange={e => this.updateName(e.target.value)}
/>
<input
type="submit"
value="Submit"
onClick={event => this.handleSubmit(event)}
/>
</form>
</div>
);
}
}
The problem is that when I click the submit, my backend reports
Started POST "/hello_world" for ::1 at 2017-07-07 15:30:44 +0200 Processing by HelloWorldController#create as HTML Parameters: {"type"=>"SAVE_NAME", "name"=>"Stranger", "hello_world"=>{"type"=>"SAVE_NAME", "name"=>"Stranger"}} Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms) ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
For one, I don't understand why the parameters seem to be passed twice, but that's not even generating a warning, so don't care for now.
The problem is that I don't see a way to obtain the CSRF tokens in my react code to use in the post
requests
should I just disable CSRF? or is there a better way?
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
Rails handles CSRF attacks by appending authenticity_token
to every Non-GET requests(POST,PUT/PATCH and DELETE). The error means you are not sending authencity_token
in the request params, You should append an unique authenticity_token
to the params
, something like "authuenticity_token" => "BsfdgtZ1hshxgthjj"
which should resolve the issue.
react_on_rails
deals with this issue by providing two helpers. From the react_on_rails
documentation:
Rails has built-in protection for Cross-Site Request Forgery (CSRF), see Rails Documentation. To nicely utilize this feature in JavaScript requests, React on Rails provides two helpers that can be used as following for POST, PUT or DELETE requests:
import ReactOnRails from 'react-on-rails';
// reads from DOM csrf token generated by Rails in <%= csrf_meta_tags %>
csrfToken = ReactOnRails.authenticityToken();
// compose Rails specific request header as following { X-CSRF-Token: csrfToken, X-Requested-With: XMLHttpRequest }
header = ReactOnRails.authenticityHeaders(otherHeader);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With