万年素人からHackerへの道

万年素人がHackerになれるまで殴り書きするぜ。

React jQuery JavaScript Phoenixでハマり

APIとしてPhoenixで生成し、

mix phoenix.gen.json Book books title:string category:string 

ReactでのPOSTをこうしていた。

            $.ajax({
                url: this.props.url,
                dataType: 'json',
                method: 'POST',
                data:this.state.editingBook,
                cache: false,
                success: function(data) {
                    this.setState({
                        message: "Successfully added book!"
                    });
                    this.reloadBooks('');
                }.bind(this),
                error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                    this.setState({
                        message: err.toString()
                    });
                }.bind(this)
            });

400 BAD requestとか出まくり。

router.exの設定は

  scope "/api", Jikken do
      pipe_through :api
      resources "/books", BookController, except: [:new, :edit]
  end

となっている。 最後のスラッシュ不要?と思い /api/books//api/booksにしたのは意味が無い。

まずはこいつ。JSONとして送るようにしていたのに

data:this.state.editingBook,

となっていたのが問題。(他のをコピペしたのが悪いだろw

data: JSON.stringify({book:this.state.editingBook}),

とする。{単数名:POSTするオブジェクト}だ。 左はあくまでキーなのだが、それを抜かして。

data: JSON.stringify(this.state.editingBook),

あとは以下も追加しなければならなかった。

                // これら必須
                contentType: 'application/json',
                beforeSend: function(req) {
                    req.setRequestHeader('Accept', 'application/json');
                },

RFC的にapplication/jsonが良いようだ。 JSONのContent-Typeは「 text/javascript 」でなく「application/json」で。 – FlatLabs

フォームデータの場合だとapplication/x-www-form-urlencodedになっていて サーバ側でうまくデータの受取ができないことがあります。

[jQuery] $.ajaxで Content-Typeを指定する

最終形態

            $.ajax({
                url: this.props.url,
                dataType: 'json',
                method: 'POST',
                // data:this.state.editingBook,
                data: JSON.stringify({book:this.state.editingBook}),
                // これら必須
                contentType: 'application/json',
                beforeSend: function(req) {
                    req.setRequestHeader('Accept', 'application/json');
                },
                cache: false,
                success: function(data) {
                    this.setState({
                        message: "Successfully added book!"
                    });
                    this.reloadBooks('');
                }.bind(this),
                error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                    this.setState({
                        message: err.toString()
                    });
                }.bind(this)
            });