【问题标题】:Passing Props to New Component - ReactJS将道具传递给新组件 - ReactJS
【发布时间】:2018-09-16 20:19:05
【问题描述】:

想知道我是否可以得到一些帮助。我正在建立一个工作委员会,并使用 github 工作作为我的工作 API 提要。到目前为止,这是我的项目的代码框链接:

https://codesandbox.io/s/34kzz5k6k1 (您需要 CORS chrome 插件才能使 api 工作)。

基本上:

  1. 在我的 index.js 文件中,我将调用我的“ComponentDidMount”中的 API。
  2. 默认情况下,工作会在我的页面上显示为“纽约”。
  3. 当您在“伦敦”中搜索“开发人员”职位时,在我的“HandleSubmit”中,您可以看到我正在将结果推送到新的 URL“/jobresults”。
  4. 我正在使用浏览器路由器来执行此操作。

我遇到的问题。所以我的默认工作仍然出现在 /jobresults 上。以及显示在下方的“伦敦”搜索结果。

如何让“伦敦”职位只显示在此页面上?

我想我可以尝试在整个前端构建一个工作板。但现在我想我也需要后端的 REST 路由?

也许将我的 API 调用保存在数据库中。然后在“显示”路线上显示结果?

如果您能提供任何指导,那就太好了!

谢谢。

【问题讨论】:

  • 你可以通过路由传递值 - 检查文档 - 没有参数时显示默认值

标签: reactjs api browser router


【解决方案1】:

这里有很多需要修改的地方。您构建应用程序的方式是反模式(非标准/不良做法),随着应用程序变得更加动态,您会更加头疼。

我已经着手重组了整个应用程序。我鼓励你解构它并遵循应用程序流程,然后接受你的项目并相应地修复它。

工作示例:https://codesandbox.io/s/v873j0600y(仍需要 CORS 扩展)


index.js

import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import JobForm from "./components/JobForm";
import JobResults from "./components/JobResults";
import NavHeader from "./components/NavHeader";
import "uikit/dist/css/uikit.min.css";
import "./styles.css";

const App = () => (
  <main>
    <BrowserRouter>
      <section>
        <NavHeader />
        <Switch>
          <Route exact path="/" component={JobForm} />
          <Route path="/jobs" component={JobResults} />
          <Route path="/jobresults/:id" component={JobResults} />
        </Switch>
      </section>
    </BrowserRouter>
  </main>
);

render(<App />, document.getElementById("root"));

NavHeader.js

import React from "react";
import { Link } from "react-router-dom";

export default () => (
  <header>
    <nav>
      <ul style={{ listStyleType: "none" }}>
        <li style={{ display: "inline", marginRight: 20 }}>
          <Link to="/">Home</Link>
        </li>
        <li style={{ display: "inline", marginRight: 20 }}>
          <Link to="/jobs">Jobs</Link>
        </li>
      </ul>
    </nav>
  </header>
);

JobForm.js

import React, { Component } from "react";

export default class JobForm extends Component {
  state = { searchData: "", cityData: ""};

  // HANDCHANGE FOR JOB SEARCH
  handleChange = e => this.setState({ searchData: e.target.value });

  // HANDLE CHANGE FOR LOCATION SEARCH
  handleChangeLocation = e => this.setState({ cityData: e.target.value });

  // HANDLE SUBMIT
  handleSubmit = e => {
    e.preventDefault();
    const { cityData, searchData } = this.state;
    if (!cityData || !searchData) return;
    this.props.history.push(
      `/jobresults/positions?description=${searchData}&location=${cityData}`
    );
  };

  render = () => (
    <section className="hero homepage">
      <div className="container">
        <h1 className="title has-text-white">USA Creative City</h1>
        <h2 className="title has-text-white">Start your job search here!</h2>
        <form className="level-item" onSubmit={this.handleSubmit}>
          <div className="inputstyle field has-addons">
            <div className="control ">
              <input
                className="uk-input"
                type="text"
                placeholder="Software Engineer..."
                onChange={this.handleChange}
                style={{ width: 200 }}
              />
            </div>
            <div className="control ">
              <input
                className="uk-input"
                type="text"
                placeholder="City"
                onChange={this.handleChangeLocation}
                style={{ width: 200 }}
              />
            </div>
            <div className="control">
              <button
                style={{ width: 200 }}
                className="uk-button uk-button-primary"
              >
                <i
                  style={{ marginRight: 10 }}
                  className="fas fa-search"
                  aria-hidden="true"
                />Search Jobs
              </button>
            </div>
          </div>
        </form>
      </div>
    </section>
  );
}

JobResults.js

import isEmpty from "lodash/isEmpty";
import React, { Component, Fragment } from "react";
import axios from "axios";
import qs from "qs";
import Spinner from "./Spinner";
import ShowResults from "./ShowResults";
import NoResults from "./NoResults";

const getRandomInt = max => Math.floor(Math.random() * Math.floor(max));
const locations = ["Los Angeles", "New York", "San Mateo", "San Francisco"];
const descriptions = ["Developer", "Engineer", "MySQL", "MongoDB"];

export default class JobResults extends Component {
  state = { isLoading: true, jobs: [], error: "" };

  componentDidUpdate = (prevProps, prevState) => {
    if (this.props.location.pathname !== prevProps.location.pathname) {
      this.setState({ isLoading: true }, () => this.fetchData());
    }
  };

  componentDidMount = () => this.fetchData();

  fetchData = () => {
    let { description, location } = qs.parse(this.props.location.search, {
      ignoreQueryPrefix: true
    });

    if (!description || !location) {
      description = descriptions[getRandomInt(3)];
      location = locations[getRandomInt(3)];
    }

    axios(`https://jobs.github.com/positions.json?description=${description}&location=${location}`)
      .then(({ data }) => this.setState({ isLoading: false, jobs: data.slice(0, 9) }))
      .catch(err => this.setState({ isLoading: false, err: err.toString() }));
  };

  render = () =>
    this.state.isLoading 
     ? <Spinner />
     : <section>
        <h3 style={{ textAlign: "center" }} className="has-text-centered animated shake slow">
          RESULTS
        </h3>
        <div className="columns is-multiline">
          {isEmpty(this.state.jobs) 
            ? <NoResults err={this.state.err} />
            : <ShowResults jobs={this.state.jobs} />
          }
        </div>
      </section>
    );
}

ShowResults.js

import map from "lodash/map";
import React from "react";

export default ({ jobs }) => (
  map(jobs, ({ id, created_at, company_logo, title, company, location, url }) => (
      <div className="result" key={id}>
        <img className="image" src={company_logo} />
        <h4 className="has-text-left purple">Location: {title}</h4>
        <h5 className="has-text-left purple">
          Created on: {created_at}
        </h5>
        <h5 className="has-text-left purple">Company: {company}</h5>
        <h5 className="has-text-left purple">Location: {location}</h5>
        <a className="uk-button uk-button-primary" href={url} target="_new">
          apply on github
        </a>
        <a
          className="uk-button uk-button-primary"
          style={{ marginTop: 10 }}
          href={url}
          target="_new"
        >
          apply on creative jobs
        </a>
      </div>
    )
);

NoResults.js

import React from "react";

export default ({ err }) => (
  err 
    ? <p style={{ textAlign: "center", color: "red" }}>
        <i style={{ marginRight: 5 }} className="fas fa-exclamation-circle" /> 
        {err}
      </p>
    : <p style={{ textAlign: "center", color: "grey" }}>
        <i style={{ fontSize: 22, marginRight: 5 }} className="far fa-calendar-times"/>
        No jobs matching that criteria.
      </p>
);

Spinner.js

import React from "react";

const spinners = () => {
  let children = [];
  for (var i = 1; i < 13; i++) {
    children.push(<div key={i} className={`sk-circle${i} sk-circle`} />);
  }
  return children;
};

export default () => <div className="sk-fading-circle">{spinners()}</div>;

【讨论】:

  • 嗨@matt-carlotta,感谢您的帖子和留言,非常感谢!不过,我是新手(5 个月 + 1 个项目)。因此,尽管我很欣赏你所做的改变,但我不明白你所做的很多事情以及为什么。您已经重新设计了完整的应用程序... 1) 为什么这种方法更好? 2) 什么是“从“lodash/isEmpty”导入 isEmpty?3) 什么是“从“qs”导入 qs? 4) 你能准确分解 JobResults.js 中发生的事情吗? JS 语法似乎很高级。
  • 我感谢您为帮助我所做的工作,但是您已经更改/添加了很多,如果您可以为您在 CodeSandbox 链接中所做的每项更改添加 cmets,那将是真的很有帮助。谢谢。
  • 与此同时,我将继续尝试自己研究/分解所有内容。谢谢!
  • 另外你为什么在类组件中添加“默认”?
  • 嗨@matt-calotta,我已经在您的代码和框链接中添加了问题作为cmets。请你回答他们,(在代码中也是 cmets)?谢谢!
猜你喜欢
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2020-11-19
相关资源
最近更新 更多