I'm working on a personal project where I'm pulling an API through Fetch; at the moment I can send the call from my index.js file to a TSX component that calls the API URL when my SearchButton component is clicked, but the search term needs to be declared in index.js.
Here's my SearchButton code (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;
I want to change that so a user can search for an article from the API by using a HTML input to submit a topic which would amend the API URL. For instance, if I searched Bitcoin, it would search https://API-${Bitcoin}.com. Due to CORS policy blocking, I can't just call the API in my TSX file as it has to go from localhost:3000 > localhost:4000 via the Node JS file.
At the moment, my input renders the user's query into the console, but I can't seem to get it over to my index.js file. How can I pass a value that's either in the console.log, or from the input's value, through to my Node JS index.js file?
Here's my SearchBar file that handles my Input (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 here's my index.js Node JS file (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:
I have a TSX component that is an input (A - value={this.state.searchString}).
I want that input's value to go to a Node JS file to append a URL via a const (B - const SEARCH_QUERY).
I know what to pull from A, and where to put it in B, but don't know how to do so.
Full tech stack
Using Fetch API, React, TypeScript, Node JS and Webpack.
File paths
- SearchButton:
project/frontend/src/components/SearchButton/SearchButton.tsx - SearchBar:
project/frontend/src/components/SearchBar/SearchBar.tsx - Node JS handler:
project/backend/index.js