2017-07-25 63 views
1

我正在開發一個使用Express.js和React的簡單應用程序,開發環境(本地計算機)中的兩個應用程序位於不同的端口上,服務器(Express) localhost:3001和localhost:3000上的前端(React)。使用Fetch API,Express無法從React接收參數

我遇到的問題是嘗試使用Fetch API Express從前端發送數據不會收到React通過POST發送的數據。我做了一個測試,從一個正常的形式做一個POST,並且服務器確實接受了我通過POST發送的參數,所以我認爲這個問題是使用Fetch API從Javascript調用的。

在Express中我已經安裝了cors模塊來接受不屬於同一個域的請求,但問題仍然存在。

以下是爲了更好理解而編寫的代碼片段。如果您的生產環境,將舉辦兩個前端和服務器,你的請求最終將不必處理CORS

... 
// handler recieves the 'e' event object 
formPreventDefault(e) { 
    var headers = new Headers(); 
    headers.append('Accept', 'application/json, application/xml, text/plain, text/html, *.*'); 
    headers.append('Content-Type', 'multipart/form-data; charset=utf-8'); 
    headers.append('Access-Control-Allow-Origin', '*'); 
    headers.append('Access-Control-Allow-Headers', 'Content-Type'); 

    var myForm = document.getElementById('myForm'); 
    var formData = new FormData(myForm); 
    formData.append('email', '[email protected]'); 
    formData.append('password', '12345'); 

     var options = { 
     headers: headers, 
     mode: 'no-cors', // crossdomain * 
     method: 'post', 
     body: JSON.stringify({ 'email': '[email protected]', 'password': '12345' }) // formData 
    }; 

    var request = new Request('http://localhost:3001/user/signin', options); 

    fetch(request).then(function(response) { 
     console.log("Success"); 
     return response; 
    }).then(function(json) { 
     console.log(json); 
     }).catch(function(err) { 
     console.log("Error " + err); 
    }) 

    // prevent submit form 
    e.preventDefault(); 

    } 

    render() { 
    return (
     <div className="row"> 
     <div className="col-md-4 "> 
      <form id="myForm" action="http://localhost:3001/user/signin" method="post" onSubmit={this.formPreventDefault}> 
       <div className="form-group"> 
        <label htmlFor ="email">Email address</label> 
        <input type="email" className="form-control" id="email" name="email" placeholder="Email" /> 
       </div> 
       <div className="form-group"> 
        <label htmlFor ="password">Password</label> 
        <input type="password" className="form-control" id="password" name="password" placeholder="*******" /> 
       </div> 
       <button type="submit" className="btn btn-default">Submit</button> 
       </form> 
     </div> 
     </div> 
    ); 
    } 
} 
... 

快遞控制器

... 
// Handle User Sign In on POST 
exports.user_create_post = function(req, res) { 
    console.log(req.body); // This always returns an empty value 
    //Check that the name field is not empty 
    req.checkBody('email', 'Email address is required').notEmpty(); 
    req.checkBody('password', 'Password is required').notEmpty(); 

    //Run the validators 
    var errors = req.validationErrors(); 

    //Create a genre object with escaped and trimmed data. 
    var user = new User(
     { email: req.body.email, password: req.body.password } 
    ); 

    if (errors) { 
     //If there are errors render the form again, passing the previously entered values and errors 
     // res.render('users/sign_up', { title: 'Sign Up', user: user, errors: errors }); 
     res.json({ user: user, errors: errors }); 
     return; 
    } 
    else { 
     // Data from form is valid. 
     //Check if User with same email already exists if not the new user is saved 
     User.findOne({ 'email': req.body.email }) 
      .exec(function(err, found_user) { 
       if (err) { return next(err); } 

       if (found_user) { 
        //User exists, redirect to the home page 
        // res.render('users/home', { title: 'Home', user: found_user }); 
        res.json({ user: found_user }); 
       } 
       else { 
        // Save user 
        user.save(function (err) { 
         if (err) { return next(err); } 

         // Create session 
         req.session.user_id = user._id.toString(); 

         // User saved. Display user profile page 
         // res.render('users/home', { title: 'Home', user: user }); 
         res.json({ user: user }); 
        }); 

       } 

      }); 
    } 
}; 
... 

歡迎任何幫助

+0

由於這兩種表達和反應是相同的起源不是,對於讀取請求時,你應該確保'{模式:「CORS」}'設置了提取選項。通過在fetch()之後的第一個.then()中記錄'response'對象或response.status值來驗證cors是否正在工作,或者如果在resposne中返回了一些HTTP錯誤代碼可能很有用。此外,通過檢查瀏覽器上的開發者控制檯的網絡選項卡,以驗證請求是否有問題,可能有助於驗證API HTTP請求/響應。 –

+0

我的模式:'no-cors'「在提取選項中。這是響應對象從Resquest返回到Express服務器:響應{type:「opaque」,url:「」,redirected:false,status:0,ok:false,statusText:「」,標題:標題,bodyUsed :false} – Wilcho

回答

-1

。在這種情況下,我建議在您的前端將Port 3000定位爲Fetch請求,並在您的Frontend服務器上使用「代理」功能Proxying API Requests in Development進行開發。

基本上,把這個在您的package.json

"proxy": "http://localhost:3001", 

,改變您的要求:

var request = new Request('http://localhost:3000/user/signin', options); 

編輯 清理爲獲取工作所需的申請:

fetch('http://localhost:3000/user/signin', { 
    method: 'POST', 
    headers: { 
     'Content-Type': 'application/json', 
    }, 
    body: JSON.stringify({ 'email': '[email protected]', 'password': '12345' }) // formData 
}).then(function(response) { 
... 
+0

這不起作用 – Wilcho

+0

您需要更具體。什麼沒有用?請求永遠不會到達您的後端服務器?請求已達到,但內容是空的? – nAv

+0

如果它到達您的服務器,但無法讀取內容,而不是使用'multipart/form-data; charset = utf-8'試試把你的頭設置爲'Content-Type':'application/json' – nAv

0

我已經想通了出了如何解決這個問題,這裏的代碼在這個帖子的幫助下https://github.com/matthew-andrews/isomorphic-fetch/issues/34

我希望幫助別人

感謝您的幫助我

... 
// handler recieves the `e` event object 
    formPreventDefault(e) { 

     var headers = new Headers(); 
     headers.append('Content-Type', 'application/json'); 

     var email = document.getElementById('email').value; 
     var password = document.getElementById('password').value; 

     if(email !== '' && password !== '') { 

      var options = { 
       method: 'POST', 
      headers: headers, 
      mode: 'cors', 
      cache: 'default', 
       body: JSON.stringify({ 'email': email, 'password': password }) // formData 
      }; 

      var request = new Request('http://localhost:3001/user/signin', options); 

      fetch(request).then(function(response) { 

      console.log("Success"); 
       return response; 

      }).then(function(json) { 

      console.log(json.errors); 

      }).catch(function(err) { 

      console.log("Error " + err); 

      }) 

     } 

     // prevent submit form 
     e.preventDefault(); 

    } 
... 
0

您的主要問題是,你沒有設置你的要求的身體是你的表單數據。相反,你手動編碼你的表單數據爲json。大的傾斜:你創建了formData變量,但從未在任何地方使用它。

試試這個:

options = { 
    headers: headers, 
    mode: 'no-cors', // crossdomain * 
    method: 'post', 
    body: formData 
}; 
相關問題