我正在处理一个个人项目,在这个项目中,我正在通过Fetch提取一个API;目前,我可以将调用从我的index.js文件发送到一个TSX组件,当我的SearchButton组件被单击时,该组件调用API,但是搜索术语需要在index.js中声明。
这里是我的SearchButton代码(TSX):
import React, { useState } from 'react'
function SearchButton() {
const [ newsResponse, setNewsResponse ]= useState(null);
function queryOnClick() {
fetch(`http://localhost:4000/news-api`, {
headers: { 'Content-Type': 'application/json' }
})
.then((response) => response.json())
.then((result) => {
console.log('result:', result);
setNewsResponse(result);
})
.catch((ex) => {
console.log('error:', ex);
});
}
return (
<div className="theme--white">
<button className="search__button padding-1 margin-1 margin-left-6" onClick={queryOnClick}>
Click to search
</button>
{newsResponse && newsResponse.articles ? (
<div className="results__container padding-2 theme--mist">
{newsResponse.articles.map((article: {
title: React.ReactNode;
author: string;
content: string;
url: string;
}) => (
<div className="article__container box-shadow padding-2 margin-4 margin-left-6 margin-right-6 theme--white">
<h2 className="article__title padding-bottom-2 margin-bottom-2">{article.title}</h2>
<h3 className="article__author padding-bottom-2 margin-bottom-2">Written by: {article.author || 'An uncredited author'}</h3>
<p className="article__content">
{article.content.length > 150 ?
`${article.content.substring(0, 150)}... [Article shortened - Click the URL below to read more]` : article.content
}
</p>
<div className="article__url margin-top-2">
<p>
<p>Source:</p>
<a href={article.url}>{article.url}</a>
</p>
</div>
</div>
))}
</div>
) : null}
</div>
);
}
export default SearchButton;我想改变这一点,这样用户就可以通过使用HTML输入来提交修改API URL的主题来搜索API中的文章。例如,如果我搜索比特币,它就会搜索https://API-${Bitcoin}.com。由于CORS策略阻塞,我不能只调用TSX文件中的API,因为它必须通过Node文件从localhost:3000 > localhost:4000调用。
目前,我的输入将用户的查询呈现到控制台中,但我似乎无法将它转到我的index.js文件中。如何将console.log中或输入值中的值传递给我的Node index.js文件?
这里是我的SearchBar文件,它处理我的输入(TSX):
import React, { Component } from 'react';
type SearchBarProps = {
searchNews: (text: string) => void;
}
type SearchBarState = {
searchString: string;
}
class SearchBar extends Component<SearchBarProps, SearchBarState> {
static defaultProps = {
searchNews: (text: string) => {}
}
state = {
searchString: ''
}
searchNews = (e: any) => {
const { searchString } = this.state
if(e.key === 'Enter' && searchString !== '') {
e.preventDefault();
e.stopPropagation();
this.props.searchNews(searchString)
console.log(searchString)
}
}
onSearchTextChange = (e: any) => {
this.setState({
searchString: e.target.value.trim()
})
}
render() {
return (
<div>
<form>
<div>
<input
id="search"
type="search"
value={this.state.searchString}
onChange={this.onSearchTextChange}
onKeyPress={e => this.searchNews(e)} placeholder="Search" />
</div>
</form>
</div>
);
}
}
export default SearchBar;...And这里是我的index.js节点JS文件(JS):
/*
* Libs
*/
const express = require('express');
const fetch = require('node-fetch');
const cors = require('cors');
const app = express();
/*
* Constants
*/
const PORT = 4000;
const API_KEY = 'x';
const SEARCH_QUERY = "Bitcoin";
const SORT_BY = "popularity";
const PAGE_SIZE = 10;
/*
* Setup CORS - This is needed to bypass NewsAPI CORS Policy Blocking by rerouting request to localhost
*/
const corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));
/*
* Setup to request NewsAPI data using Fetch API
*/
app.get('/news-api', function (req, res) {
fetch(`https://newsapi.org/v2/everything?q=${SEARCH_QUERY}&sortBy=${SORT_BY}&pageSize=${PAGE_SIZE}&apiKey=${API_KEY}`, {
headers: { 'Content-Type': 'application/json' }
})
.then((response) => response.json())
.then((result) => {
console.log('result:', result);
res.json(result);
})
.catch((ex) => {
console.log('error:', ex);
res.status(400).send({
message: 'This is an error!',
error: ex
});
});
})
/*
* Start Backend API Proxy server
*/
app.listen(PORT, () => {
console.log(`=================`)
console.log(`API Connected!`)
console.log(`Listening at http://localhost:${PORT}`)
console.log(`=================`)
})TLDR:
我有一个TSX组件是一个输入(A - value={this.state.searchString})。
我希望输入的值转到一个Node文件中,通过一个const (B - const SEARCH_QUERY)附加一个URL。
我知道从A中提取什么,以及把它放在B中,但是不知道怎么做。
全技术栈
使用Fetch API、React、TypeScript、Node和Webpack。
文件路径
project/frontend/src/components/SearchButton/SearchButton.tsxproject/frontend/src/components/SearchBar/SearchBar.tsxproject/backend/index.js发布于 2021-04-19 04:00:03
本质上,您在这里要问的是如何将数据从前端传递到后端。这样做的方法是在后端的fetch请求中包含用户的搜索项。您可以将其包含在body请求的POST中,也可以将其作为查询字符串包含在POST请求中。您需要使用body来传递大量数据,但是可以使用查询字符串来完成像搜索术语这样简单的操作。
前端
将当前搜索项作为获取请求的查询参数。我使用encodeURIComponent将百分比编码应用于特殊字符。
function queryOnClick() {
// applies percent-encoding to special characters
const search = encodeURIComponent(searchString);
const url = `http://localhost:4000/news-api?search=${search}`;
fetch(url, {
...您缺少了SearchButton和SearchBar组件之间的通信。我不知道这两个组件在您的页面上是相互关联的。如果他们是兄弟姐妹,那么您将需要状态和queryOnClick函数,直到共享父函数。
我重新安排了您的所有组件,以便您能够在正确的位置访问正确的状态。
import React, { useState } from "react";
function SearchButton({ onClick }: { onClick: () => void }) {
return (
<button
className="search__button padding-1 margin-1 margin-left-6"
onClick={onClick}
>
Click to search
</button>
);
}
interface SearchBarProps {
searchNews: () => void;
searchString: string;
setSearchString: (s: string) => void;
}
function SearchBar({ searchNews, searchString, setSearchString }: SearchBarProps) {
const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" && searchString !== "") {
e.preventDefault();
e.stopPropagation();
searchNews();
}
};
const onSearchTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchString(e.target.value.trim());
};
return (
<div>
<form>
<div>
<input
id="search"
type="search"
value={searchString}
onChange={onSearchTextChange}
onKeyPress={handleKeyPress}
placeholder="Search"
/>
</div>
</form>
</div>
);
}
interface Article {
title: string;
author: string;
content: string;
url: string;
}
interface NewsResponse {
articles: Article[];
}
function ArticleList({ articles }: NewsResponse) {
return (
<div className="results__container padding-2 theme--mist">
{articles.map((article) => (
<div className="article__container box-shadow padding-2 margin-4 margin-left-6 margin-right-6 theme--white">
<h2 className="article__title padding-bottom-2 margin-bottom-2">
{article.title}
</h2>
<h3 className="article__author padding-bottom-2 margin-bottom-2">
Written by: {article.author || "An uncredited author"}
</h3>
<p className="article__content">
{article.content.length > 150
? `${article.content.substring(
0,
150
)}... [Article shortened - Click the URL below to read more]`
: article.content}
</p>
<div className="article__url margin-top-2">
<p>
<p>Source:</p>
<a href={article.url}>{article.url}</a>
</p>
</div>
</div>
))}
</div>
);
}
function SearchPage() {
const [newsResponse, setNewsResponse] = useState<NewsResponse | null>(null);
const [searchString, setSearchString] = useState("");
function queryOnClick() {
// applies percent-encoding to special characters
const search = encodeURIComponent(searchString);
const url = `http://localhost:4000/news-api?search=${search}`;
fetch(url, {
headers: { "Content-Type": "application/json" }
})
.then((response) => response.json())
.then((result) => {
console.log("result:", result);
setNewsResponse(result);
})
.catch((ex) => {
console.log("error:", ex);
});
}
return (
<div className="theme--white">
<SearchBar
searchNews={queryOnClick}
searchString={searchString}
setSearchString={setSearchString}
/>
<SearchButton onClick={queryOnClick} />
{newsResponse && newsResponse.articles ? (
<ArticleList articles={newsResponse.articles} />
) : null}
</div>
);
}
export default SearchPage;后端
您需要从请求URL的search参数访问搜索项。我们使用req.params属性来获得一个params字典。如果请求中没有"Bitcoin"参数,我们可以使用您以前的搜索项search作为默认值。
我不确定我们是否需要在这里重新编码--你会想玩这个游戏的。
app.get('/news-api', function (req, res) {
const searchQuery = req.params.search || "Bitcoin";
fetch(`https://newsapi.org/v2/everything?q=${searchQuery}&sortBy=${SORT_BY}&pageSize=${PAGE_SIZE}&apiKey=${API_KEY}`, {
...https://stackoverflow.com/questions/67150107
复制相似问题