将道具传递给新组件 - ReactJS

问题描述 投票:0回答:1

想知道我是否能得到一些帮助。我正在建立一个工作板,我正在使用github工作作为我的工作API提要。这是到目前为止我的项目的codeandbox链接:

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

基本上:

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

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

我如何才能在此页面上显示“伦敦”工作?

我以为我可以尝试在所有前端建立一个工作板。但是现在我认为我还需要在后端进行REST路由?

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

您可以提供的任何指导都会很棒!

谢谢。

reactjs api browser router
1个回答
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>;
© www.soinside.com 2019 - 2024. All rights reserved.