我是新来的反应者,也需要做其他事情,我正在努力解决一些问题。我的第一个问题是,我收到来自axios的“ get”请求,作为整个方面的响应。 (我认为我的webpack造成了一些麻烦)第二个问题是我的Axios函数将失败,并显示错误“ this.props.getBranch不是函数”。
我试图解决这些问题,并且搜索了一段时间却没有解决方案……因此,如果您能帮助我,那将是非常不错的。
我的代码 多步表单
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);
我的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;
我的动作
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);
});
};
}
减速器
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;
}
};
服务器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"));
风险部分
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配置
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"]
}
};
===编辑=== 这是我对请求的答复
<!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>
答案 0 :(得分:0)
首先,之所以总是获得整个HTML页面,是因为它是由路由管理引起的。如下所示,当您在路线中使用星号/通配符时,该部分看起来像:
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "./index.html"));
});
看起来它将处理所有请求,因此路由器描述之后将永远无法到达。尝试使用以下方法进行更改:
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "./index.html"));
});
如果您真的需要/*
在路由器声明的最后一行放置另一个。
第二:
您在props
内调用componentWillMount()
,通常在该生命周期内尚不可用。即使通常,它在componentDidMount()
生命周期中仍然不可用。根据我读过的一些文章,componentWillMount()
在当前的React版本中已被弃用。我建议您不要使用它。有两种方法可以解决此类问题,我可以向您推荐以下方法:
使用componentDidMount()
生命周期。在这种方法中,您应该放置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()方法
旧的方法是使用componentWillRecieveProps()
,但是由于不建议使用,所以建议改用getDerivedStateFromProps()
。在此生命周期阶段,不需要setTimeout()
技巧。因为道具应该已经可用。
供您参考,以下是有关不推荐使用的React Livecycles的好文章:https://hackernoon.com/problematic-react-lifecycle-methods-are-going-away-in-react-17-4216acc7d58b
====更新19年1月22日======
只是一个建议,通常我们可以直接将redux动作直接调用到组件,而不是将它们作为道具传递。因此,您可以按照以下步骤从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
然后将您的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