如何修复整个HTML的获取请求和响应

时间:2019-01-20 16:30:14

标签: javascript reactjs webpack redux axios

我是新来的反应者,也需要做其他事情,我正在努力解决一些问题。我的第一个问题是,我收到来自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>

1 个答案:

答案 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版本中已被弃用。我建议您不要使用它。有两种方法可以解决此类问题,我可以向您推荐以下方法:

  1. componentDidMount()方法

使用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