[英]How to fix get request and response with whole html
I'm new to react, redux and all the other stuff and I am struggling with some problems. 我是新来的反应者,也需要做其他事情,我正在努力解决一些问题。 My first problem is that I receive from an axios "get" request as a response my whole side.
我的第一个问题是,我收到来自axios的“ get”请求,作为整个方面的响应。 (I think my webpack makes some trouble) The second problem is that my Axios function will fail with the error "this.props.getBranch is not a function".
(我认为我的webpack造成了一些麻烦)第二个问题是我的Axios函数将失败,并显示错误“ this.props.getBranch不是函数”。
I have tried to fix the problems and searched for a while without a solution... So it would be great if you could help me. 我已经尝试解决问题,并且搜索了一段时间却没有解决方案...因此,如果您能帮助我,那将是很棒的。
my code Multistep Form 我的代码多步骤表单
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import RiskDetails from "./Step1/RiskDetails";
import { getBranch } from "../../actions/riskActions";
class RiskForm extends Component {
constructor(props) {
super(props);
this.state = {
step: 1,
risikoName: "",
risikoBereich: "",
risikoKlasse: "",
branche: ""
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
nextStep() {
let step = this.state.step;
this.setState({ step: step + 1 });
}
prevStep() {
let step = this.state.step;
this.setState({ step: step - 1 });
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
onSubmit(e) {
e.preventDefault();
}
render() {
const { step } = this.state;
const { risikoName, risikoBereich, risikoKlasse, branche } = this.state;
const values = { risikoName, risikoBereich, risikoKlasse, branche };
switch (step) {
case 1:
return (
<RiskDetails
nextStep={this.nextStep}
onChange={this.onChange}
values={values}
getBranch={getBranch}
/>
);
}
}
}
RiskForm.propTypes = {
getBranch: PropTypes.func.isRequired
};
export default connect(
state => {
return {};
},
{ getBranch }
)(RiskForm);
my riskDetails 我的风险详细信息
import React, { Component } from "react";
import { Grid, Form } from "semantic-ui-react";
import PropTypes from "prop-types";
class RiskDetails extends Component {
componentWillMount() {
this.props.getBranch().then(res => {
console.log(res);
});
}
render() {
const { value } = this.props;
return (
<Grid container>
<Grid.Row>
<Grid.Column width={8}>
<Form>
<Form.Select
fluid
label={value.branch}
//options={this.state.branch}
placeholder={value.branch}
/>
</Form>
</Grid.Column>
</Grid.Row>
</Grid>
);
}
}
RiskDetails.propTypes = {
getBranch: PropTypes.func.isRequired
};
export default RiskDetails;
my actions 我的行动
import axios from "axios";
import { FETCH_BRANCH } from "./types";
export function createRisk(event) {
return dispatch => {
return axios.post("/api/risk", event);
};
}
export function fetchRiskDetails(risk) {
return {
type: FETCH_BRANCH,
risk
};
}
export function getBranch() {
return dispatch => {
console.log("starting get request")
return axios.get("/api/risk").then(res => {
dispatch(fetchRiskDetials(res.data));
console.log(res.data);
});
};
}
reducer 减速器
import { FETCH_BRANCH } from "../actions/types";
const initialState = {
risk: {}
};
export default (state = initialState, action = {}) => {
switch (action.type) {
case FETCH_BRANCH:
return {
risk: action.risk
};
default:
return state;
}
};
server index.js 服务器index.js
import express from "express";
import path from "path";
import bodyParser from "body-parser";
import mongoose from "mongoose";
import cors from "cors";
//WEBPACK
import webpack from "webpack";
import webpackMiddleware from "webpack-dev-middleware";
import webpackHotMiddleware from "webpack-hot-middleware";
import wepbackConfig from "../webpack.config.dev";
//IMPORT ALL API ROUTES
import authRoute from "./routes/auth";
import signUpRoute from "./routes/signup";
import companyRoute from "./routes/company";
import riskRoute from "./routes/risk";
import recommendationRoute from "./routes/recommendation";
let app = express();
const compiler = webpack(wepbackConfig);
app.use(
webpackMiddleware(compiler, {
hot: true,
publicPath: wepbackConfig.output.publicPath,
noInfo: true
})
);
app.use(cors());
app.use(express.static(path.join(__dirname, "dist")));
app.use(webpackHotMiddleware(compiler));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// SET UP YOUR DB FOR THE API
// =============================================================================
var url = "mongodb://localhost:27017/blubb";
mongoose
.connect(
url,
{ useNewUrlParser: true, useCreateIndex: true }
)
.then(() => console.log("connected to DB"))
.catch(err => console.log(err));
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "./index.html"));
});
// ROUTES FOR OUR API
// =============================================================================
app.use("/api/auth", authRoute);
app.use("/api/risk", riskRoute);
app.listen(3000, () => console.log("running"));
risk part 风险部分
import express from "express";
import {
validatePostInput,
validateDeleteInput
} from "../shared/validation/risk";
import Risk from "../models/risk";
import authenticate from "../middleware/authenticate";
let router = express.Router();
router.get("/", (req, res) => {
console.log("hi form server");
Risk.find(function(err, risks) {
if (err) {
console.log(err);
} else {
res.status(400).json(risks);
}
});
});
//create new risk
router.post("/", authenticate, (req, res) => {
const { errors, isValid } = validatePostInput(req.body);
console.log(req.body);
if (isValid) {
const { risikoName, risikoBereich, risikoKlasse, createdBy } = req.body;
var newRisk = new Risk({
risikoName,
risikoBereich,
risikoKlasse,
createdBy
});
// save the risk
newRisk.save(function(err) {
if (err) {
return res.status(500).json({ error: err });
}
res.json({ success: true });
});
} else {
res.status(400).json(errors);
}
});
//delete risk
router.delete("/", (req, res) => {
const { errors, isValid } = validateDeleteInput(req.body);
if (isValid) {
const { id } = req.body;
Risk.remove({ _id: id }, function(err, risk) {
if (err) return res.status(500).json({ error: err });
res.json({ success: true });
});
} else {
res.status(400).json(errors);
}
});
export default router;
webpack config webpack配置
import path from "path";
import webpack from "webpack";
export default {
mode: "development",
entry: [
"webpack-hot-middleware/client",
path.join(__dirname, "client/index.js")
],
output: {
filename: "bundle.js",
path: "/",
publicPath: "/"
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.js$/,
include: [
path.join(__dirname, "client"),
path.join(__dirname, "server/shared")
],
loaders: ["react-hot-loader/webpack", "babel-loader"]
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.s[a|c]ss$/,
loader: "sass-loader!style-loader!css-loader"
},
{
test: /\.(jpg|png|gif|jpeg|woff|woff2|eot|ttf|svg)$/,
loader: "url-loader?limit=100000"
}
]
},
resolve: {
extensions: [".js"]
}
};
===EDIT=== Here is my response from a request ===编辑===这是我对请求的回应
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Tool</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
First, the reason why you always get whole HTML page, I guess it caused by routing management. 首先,我之所以总是获得整个HTML页面,是因为它是由路由管理引起的。 Looks like the part when you using asterisk/wild card in your route as follows:
如下所示,当您在路线中使用星号/通配符时,该部分看起来像:
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "./index.html"));
});
Looks it will handle all requests, so router describe after that will never get reached. 看起来它将处理所有请求,因此路由器描述之后将永远无法实现。 Try to change it with:
尝试使用以下方法进行更改:
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "./index.html"));
});
If you really need it to have /*
put another one at very last line of router declaration. 如果您真的需要
/*
在路由器声明的最后一行加上另一个。
2nd : 第二名
You call props
inside componentWillMount()
, which usually props not yet available at that lifecycle. 您可以在
componentWillMount()
内部调用props
,该对象通常在该生命周期中尚不可用。 Even usually it still not available in componentDidMount()
lifecycle. 即使通常,它在
componentDidMount()
生命周期中仍然不可用。 Based on some articles I read, componentWillMount()
is deprecated in current React version. 根据我阅读的一些文章,在当前的React版本中不赞成使用
componentWillMount()
。 I suggest you to not using it. 我建议您不要使用它。 There are 2 ways to solve this kind of problem I can recommend you as follow:
有两种方法可以解决此类问题,我可以向您推荐以下方法:
Using componentDidMount()
lifecycle. 使用
componentDidMount()
生命周期。 In this method, you should put setTimeout()
to give the component a time to receive props. 在此方法中,应放置
setTimeout()
以便组件有时间接收道具。
componentDidMount() {
setTimeout(()=>{
this.props.getBranch().then(res => {
console.log(res);
});
},
100);//Try with 0 first ( not put this parameter ), if it is not works, try to increase by 100, 200 etc.
}
2. getDerivedStateFromProps() method 2. getDerivedStateFromProps()方法
The old way is using componentWillRecieveProps()
, but because it is deprecated, I recommend to use getDerivedStateFromProps()
instead. 旧方法是使用
componentWillRecieveProps()
,但是由于不建议使用,所以我建议改用getDerivedStateFromProps()
。 In this life cycle phase, it doesn't need setTimeout()
trick. 在此生命周期阶段,不需要
setTimeout()
技巧。 Because props should already available. 因为道具应该已经可用。
For your reference, here is good article about deprecated React Livecycles: https://hackernoon.com/problematic-react-lifecycle-methods-are-going-away-in-react-17-4216acc7d58b 供您参考,以下是有关过时的React Livecycles的好文章: https ://hackernoon.com/problematic-react-lifecycle-methods-are-going-away-in-react-17-4216acc7d58b
==== UPDATE Jan 22 '19 ====== ====更新'19年1月22日======
Just a suggestion, usually we can just call redux actions directly to the component instead passing them as props. 只是一个建议,通常我们只能将redux动作直接调用到组件,而不是将它们作为道具传递。 So you can clean up
RiskForm
component from Redux wiring as follow: 因此,您可以按照以下步骤从Redux接线中清理
RiskForm
组件:
import React, { Component } from "react";
// import { connect } from "react-redux"; //!!! move connect() inside RiskDetails instead
import PropTypes from "prop-types";
import RiskDetails from "./Step1/RiskDetails";
// import { getBranch } from "../../actions/riskActions"; //!!!!Move this to RiskDetails component
class RiskForm extends Component {
constructor(props) {
super(props);
this.state = {
step: 1,
risikoName: "",
risikoBereich: "",
risikoKlasse: "",
branche: ""
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
nextStep() {
let step = this.state.step;
this.setState({ step: step + 1 });
}
prevStep() {
let step = this.state.step;
this.setState({ step: step - 1 });
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
onSubmit(e) {
e.preventDefault();
}
render() {
const { step } = this.state;
const { risikoName, risikoBereich, risikoKlasse, branche } = this.state;
const values = { risikoName, risikoBereich, risikoKlasse, branche };
switch (step) {
case 1:
return (
<RiskDetails
nextStep={this.nextStep}
onChange={this.onChange}
values={values}
// getBranch={getBranch}//!!! Don't need this props, import inside RiskDetails directly
/>
);
}
}
}
RiskForm.propTypes = {
getBranch: PropTypes.func.isRequired
};
/*
export default connect(
state => {
return {};
},
{ getBranch }
)(RiskForm);*/
export default RiskForm;//You can remove connect() and leave this as dumb component
Then make your RiskDetails
component as Container/smart component as follow ( please pay attention at comments I made with exclamation/'!' ): 然后使您的
RiskDetails
组件成为Container / smart组件,如下所示(请注意我用感叹号/'!'发表的评论):
import React, { Component } from "react";
import {connect} from 'react-redux';//!!! Import redux here
import { Grid, Form } from "semantic-ui-react";
import PropTypes from "prop-types";
import { getBranch } from "../../actions/riskActions";//!!! Import action creator here
class RiskDetails extends Component {
componentWillMount() {
getBranch().then(res => {//Call the action creator directly instead using props
console.log(res);
});
}
render() {
const { value } = this.props;
return (
<Grid container>
<Grid.Row>
<Grid.Column width={8}>
<Form>
<Form.Select
fluid
label={value.branch}
//options={this.state.branch}
placeholder={value.branch}
/>
</Form>
</Grid.Column>
</Grid.Row>
</Grid>
);
}
}
RiskDetails.propTypes = {
getBranch: PropTypes.func.isRequired
};
export default connect(null)(RiskDetails);//!!! Connect this component with redux
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.