简体   繁体   English

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

[英]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: 有两种方法可以解决此类问题,我可以向您推荐以下方法:

  1. componentDidMount() method componentDidMount()方法

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM