質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

1728閲覧

[Rails API][React]axiosを用いて"POST"したい!

uk_63

総合スコア29

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2018/12/28 06:40

編集2018/12/28 06:41

#はじめに

React初心者です。
RailsでAPIをつくり、Reactでフロント部分を書く練習をしています。
アプリケーションの内容は、ユーザー(post.author)がなにか(post.content)をつぶやくといいったシンプルなものです。

Rails => localhost:4000
React => localhost:3000を使用しています。

フォームから受け取ったデータでPost.createをしたいのですが、うまくいきません。

#API側(Rails)ファイル構造

Railsのファイルの中にcreate-react-app app_frontendしました。

####コード
routes.rb

ruby

1Rails.application.routes.draw do 2 resources :posts, only: [:index, :create, :destroy], format: 'json' 3end

posts_controller.rb

ruby

1class PostsController < ApplicationController 2 def index 3 @post = Post.all 4 render json: @post 5 end 6 7 def create 8 @post = Post.create(post: params[:post]) 9 render json: @post 10 end 11 12 def destroy 13 @post = Post.find(params[:id]) 14 if @post.destroy 15 head :no_content, status: :ok 16 else 17 render json: @post.errors, status: :unprocessable_entity 18 end 19 end 20 21 def post_params 22 params.require(:post).permit(:author, :content) 23 end 24 25end 26

#フロントエンド側(React)のファイル構造

src ├── components │ ├── List.jsx ##axios.get を用いてJSONを取得し一覧表示しています。 │ └── New.jsx ##axios.post を用いてPost.createしたい。 ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── ServiceWorker.js

####コード
App.js

js

1import React from 'react'; 2import { BrowserRouter as Router, Link, Switch, Route } from 'react-router-dom'; 3import List from './components/List'; 4import New from './components/New'; 5import './App.css'; 6 7const App = () => { 8 return ( 9 <Router> 10 <div id="App"> 11 <Header />  12 <Switch> 13 <Route exact path='/' component={ List }/> 14 <Route exact path='/new' component={ New } /> 15 </Switch> 16 <Footer /> 17 </div> 18 </Router> 19 ); 20} 21const Header = () => ( 22 <nav className="navbar navbar-expand-xl navbar-light bg-dark"> 23 <div className="container"> 24 <Link to="/" className="navbar-brand text-white">SampleTodo</Link> 25 <Link to="/new" className="navbar-brand text-white">新規投稿</Link> 26 </div> 27 </nav> 28) 29const Footer = () => ( 30 <footer className="footer footer-expand-xl bg-light"> 31 <div className="container"> 32 <p className="text-muted">SampleTodo</p> 33 </div> 34 </footer> 35) 36 37export default App; 38

components/List.jsx

jsx

1import React, { Component } from 'react'; 2import axios from 'axios' 3 4class List extends Component { 5 constructor(props) { 6 super(props) 7 this.state = { 8 posts: [] 9 }; 10 } 11 12 componentDidMount() { 13 axios.get('http://localhost:4000/posts') 14 .then((results) => { 15 this.setState({posts: results.data}) 16 }) 17 .catch((data) =>{ 18 console.log(data) 19 }) 20 } 21 22 render() { 23 const {posts} = this.state 24 return ( 25 <div> 26 {posts.map((post) => { 27 return <li key={post.id}> { post.author }{ post.content }</li> 28 })} 29 </div> 30 ); 31 } 32} 33export default List;

components/New.jsx

jsx

1import React, { Component } from 'react'; 2import axios from 'axios' 3 4class New extends Component { 5 constructor(props){ 6 super(props); 7 this.state = { 8 author: '', 9 content: '' 10 }; 11 } 12 13 handleInputValue = (event) => { 14 const field = event.target.name; 15 this.state[field] = event.target.value; 16 this.setState({ 17 [field]: this.state[field] 18 }); 19 } 20 21 handleSubmit = () => { 22 axios({ 23 method : "POST", 24 url : "http://localhost:4000/posts", 25 data : { author: this.state.author, content: this.state.content } 26 }) 27 .then((response)=> { 28 console.log(this.props) 29 this.props.history.push('/'); 30 }) 31 .catch((error)=> { 32 console.error(error); 33 }); 34 } 35 36 render() { 37 const { author, content } = this.state; 38 return ( 39 <div> 40 <p>新規投稿</p> 41 <div> 42 <form onSubmit={this.handleSubmit}> 43 <label>偉人 : </label> 44 <input type="text" name="author" value={ author } onChange={ this.handleInputValue } /> 45 <label>名言 : </label> 46 <textarea name="content" value={ content } onChange={ this.handleInputValue } /> 47 <input type="submit" value="Submit" /> 48 </form> 49 </div> 50 </div> 51 ); 52 } 53} 54 55 56export default New; 57

#起こっていること
現段階では、フォームに入力しても、URLに入力内容がくっつくだけです。
例えば、author: "テスト"content: "テストテスト"と入力すると、
URLがhttp://localhost:3000/newからhttp://localhost:3000/new?author=テスト&content=テストテストが変化するだけで、Post.createできません。

#お願いしたいこと
・問題は、components/New.jsxにある下記コードだと思うのですがどのように修正すればいいのかわからないです。

js

1 handleSubmit = () => { 2 axios({ 3 method : "POST", 4 url : "http://localhost:4000/posts", 5 data : { author: this.state.author, content: this.state.content } 6 }) 7 .then((response)=> { 8 console.log(this.props) 9 this.props.history.push('/'); 10 }) 11 .catch((error)=> { 12 console.error(error); 13 }); 14 }

・またaxiosの使い方があまりわかっていないので、わかりやすい参考サイトがあれば教えて頂きたいです。

宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

axios によって送りたいAPIへのリクエストの他に、<form /> がsubmitされたことによるリクエストが発生しているために意図しない挙動になっているものと思います。

以下にて、修正する方法を2つ挙げます。

(1) <form /> がsubmitされたときのデフォルト動作を抑止

New.jsx で、handleSubmit の冒頭、

javascript

1 handleSubmit = () => { 2 axios({ 3 method : "POST",

となっているのを以下

javascript

1 handleSubmit = (e) => { 2 e.preventDefault(); 3 axios({ 4 method : "POST",

のようにして、<form />がsubmitされたときのデフォルト動作を抑止します。

(2) <form /> を使わないようにする。

axios でリクエストを送るので <form /> 自体が不要ですから、renderで返している以下の部分

html

1 <div> 2 <form onSubmit={this.handleSubmit}> 3 <label>偉人 : </label> 4 <input type="text" name="author" value={ author } onChange={ this.handleInputValue } /> 5 <label>名言 : </label> 6 <textarea name="content" value={ content } onChange={ this.handleInputValue } /> 7 <input type="submit" value="Submit" /> 8 </form> 9 </div>

から、<form /> を取り去り、かつ、ボタンをクリックしたときにhandleSubmitが呼ばれるようにすればよいので、以下

html

1 <div> 2 <label>偉人 : </label> 3 <input type="text" name="author" value={ author } onChange={ this.handleInputValue } /> 4 <label>名言 : </label> 5 <textarea name="content" value={ content } onChange={ this.handleInputValue } /> 6 <input type="button" onClick={this.handleSubmit} value="Submit" /> 7 </div>

のように修正します。

上記の(1)または(2)の修正によって、意図通りボタンをクリックしたときに、axiosからPOSTでリクエストが送られると思います。

それと、蛇足ながらもう一点、ご質問の本題とは関係ありませんが、以下の部分

javascript

1 handleInputValue = (event) => { 2 const field = event.target.name; 3 this.state[field] = event.target.value; 4 this.setState({ 5 [field]: this.state[field] 6 }); 7 }

は、より手短かに以下でよいかと思います。

javascript

1 handleInputValue = (event) => { 2 this.setState({ 3 [event.target.name]: event.target.value 4 }); 5 }

以上参考になれば幸いです。

投稿2019/01/07 23:06

編集2019/01/07 23:30
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uk_63

2019/01/07 23:41

何度も質問に答えてくださってありがとうございます! いつも丁寧でわかりやすく参考になり、助かっています。
jun68ykt

2019/01/07 23:42

どういたしまして。解決されたようでよかったです????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問