想知道我是否能得到一些帮助。我正在构建一个工作板,并且正在使用github Jobs作为我的Jobs API feed。到目前为止,这是我的项目的codeandbox链接:
https://codesandbox.io/s/34kzz5k6k1 (您需要CORS chrome插件才能使api正常工作。)
基本上:
我遇到的问题。因此,我的默认作业仍显示在/ jobresults上。以及显示在下方的“伦敦”搜索结果。
如何仅使“伦敦”工作出现在此页面上?
我认为我可以尝试在所有前端构建工作板。但是现在我想我还需要在后端进行REST路由?
也许将我的API调用保存在数据库中。然后在“显示”路线上显示结果?
您能提供的任何指导都很棒!
谢谢。
答案 0 :(得分: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>;