首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从TSX组件中的输入标记中获取一个值,并在另一个目录中的Node文件中使用该值?

如何从TSX组件中的输入标记中获取一个值,并在另一个目录中的Node文件中使用该值?
EN

Stack Overflow用户
提问于 2021-04-18 15:11:35
回答 1查看 490关注 0票数 1

我正在处理一个个人项目,在这个项目中,我正在通过Fetch提取一个API;目前,我可以将调用从我的index.js文件发送到一个TSX组件,当我的SearchButton组件被单击时,该组件调用API,但是搜索术语需要在index.js中声明。

这里是我的SearchButton代码(TSX):

代码语言:javascript
复制
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):

代码语言:javascript
复制
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):

代码语言:javascript
复制
/*
 * 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。

文件路径

  • SearchButton: project/frontend/src/components/SearchButton/SearchButton.tsx
  • SearchBar: project/frontend/src/components/SearchBar/SearchBar.tsx
  • 节点JS处理程序: project/backend/index.js
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-19 04:00:03

本质上,您在这里要问的是如何将数据从前端传递到后端。这样做的方法是在后端的fetch请求中包含用户的搜索项。您可以将其包含在body请求的POST中,也可以将其作为查询字符串包含在POST请求中。您需要使用body来传递大量数据,但是可以使用查询字符串来完成像搜索术语这样简单的操作。

前端

将当前搜索项作为获取请求的查询参数。我使用encodeURIComponent百分比编码应用于特殊字符。

代码语言:javascript
复制
function queryOnClick() {
  // applies percent-encoding to special characters
  const search = encodeURIComponent(searchString);
  const url = `http://localhost:4000/news-api?search=${search}`;
  fetch(url, {
...

您缺少了SearchButtonSearchBar组件之间的通信。我不知道这两个组件在您的页面上是相互关联的。如果他们是兄弟姐妹,那么您将需要状态queryOnClick函数,直到共享父函数。

我重新安排了您的所有组件,以便您能够在正确的位置访问正确的状态。

代码语言:javascript
复制
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作为默认值。

我不确定我们是否需要在这里重新编码--你会想玩这个游戏的。

代码语言:javascript
复制
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}`, {
...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67150107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档