How to append string to API url onclick in React js - reactjs

I'd like to append a string to all url when I click on a button, how to do this ?
Here is the code
App.js
import React, { Component } from "react";
import Button from './Button';
let API = 'https://someurl.com/';
class App extends Component {
constructor(props) {
super(props);
this.state = {
results: []
};
this.updateUrl = this.updateUrl.bind(this);
}
componentWillMount = () => {
this.fetchData();
}
fetchData = async () => {
const response = await fetch(API);
const json = await response.json();
this.setState({
results: json.results
});
};
updateButton = (event) => {
this.setState({
API.concat('?format=fzjeozfij')
});
}
render() {
return (
<div>
<Button data={this.state} />
</div>
);
}
}
export default App;
Button.js
import React, { Component } from 'react';
class Button extends Component {
render() {
const updateButton = this.props.data;
return (
<button type="button" onClick={updateButton}>Button</button>
)
}
}
export default Button;
My goal is to get the url from const API to https://someurl.com/?format=zegizhgz
I think I have to modify the fetchData function to concat some string to the url but I'm not sure how to do it

updateButton = () => {
const nApi = `${this.state.api}?format=wookiee`;
this.setState({ api: nApi });
this.fetchData(nApi);
}
render() {
return (
<div>
<Button onClick={this.updateButton}/>
</div>
);
}
fetchData = async (api) => {
const response = await fetch(api);
const json = await response.json();
this.setState({
results: json.results
});
};
Button.jsx
import React, { Component } from 'react';
class Button extends Component {
render() {
const {onClick} = this.props;
return (
<button type="button" onClick={onClick}>Button</button>
)
}
}

Related

Access data from GraphQL in class component

I have a code which access data from GraphQL API in an arrow function:
const LinkList = () => {
const { loading, error, data } = useQuery(CURRENCIES);
if (loading) return <Loader/>;
if (error) return <pre>{error.message}</pre>
return (
<div className="options">
{data.currencies.map((currency) => {
return (
<button
key={currency}
id={currency}
className="option"
>
{currency.symbol}
{currency.label}
</button>
);
})}
</div>
);
};
But I really need to implement this piece of code with access to it in a class component. I was searching a documentation with accessing data in a classes, but nothing.
Any ideas?
You can use #apollo/client package and we can use client.query directly in the class component
import {
ApolloClient,
gql,
InMemoryCache,
NormalizedCacheObject
} from '#apollo/client';
const client = new ApolloClient<NormalizedCacheObject> ({
cache: new InMemoryCache({}),
uri: 'https://countries.trevorblades.com'
});
import * as React from 'react';
const GET_Countries = gql`
query {
countries{
code
name
}
}
`;
class App extends React.Component {
getData = async () => {
let res = await client.query({
query: GET_Countries
})
console.log(res)
// Set the state to make changes in UI
}
componentDidMount() {
this.getData()
}
render() {
return "Test";
}
}
export default App;

Cannot figure out why API JSON object will not render to React component

I cannot figure out what I am doing wrong here. I submit a request to the API and an object is returned, but I cannot seem to get the component to render.
//Code
import React, { Component } from "react"
import axios from 'axios';
class Weather extends Component {
constructor(props){
super(props)
this.state = {
posts: [],
};
}
componentDidMount() {
const query = "Paris";
const apiKey = {api key here};
const unit = "metric";
const url = "https://api.openweathermap.org/data/2.5/weather?q=" + query + "&appid=" + apiKey + "&units=" + unit;
axios.get(`${url}`)
.then(response => {
console.log(response);
this.setState({posts: response.data})
})
.catch(error => {
console.log(error);
})
}
render() {
const { posts } = this.state;
return(
<>
{posts.length ? <div>Temperature: {posts.main.temp} Description: {posts.weather[0].description}</div> : null}
</>
);
}
}
export default Weather;
enter image description here

Props not displaying from fetch call

I am trying to display recipes and not sure if I have this setup correctly. I am pulling recipes from a rails api via get fetch request. At the moment nothing is displaying.
Here is my recipe container:
import React, { Component } from 'react'
import RecipeList from '../components/RecipeList'
import RecipeInput from '../components/RecipeInput'
import { connect } from 'react-redux'
import { postRecipes } from '../actions/postRecipes.js'
import { getRecipes } from '../actions/getRecipes'
class RecipeContainer extends Component{
constructor(props){
super(props)
}
componentDidMount(){
getRecipes()
}
render(){
return (
<div>
<RecipeInput postRecipes={this.props.postRecipes} />
<RecipeList getRecipes={this.props.recipes} />
</div>
)
}
}
const mapStateToProps = state =>({
recipes: state.recipes
})
const mapDispatchToProps = dispatch =>{
return{
postRecipes: (recipe) => dispatch(postRecipes(recipe)),
getRecipes: () => dispatch(getRecipes())
// deleteRecipe: id => dispatch({type: 'Delete_Recipe', id})
}
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeContainer)
Here is my get request....notice that I am returning my Recipe component here.
export const getRecipes = () => {
const BASE_URL = `http://localhost:10524`
const RECIPES_URL =`${BASE_URL}/recipes`
return (dispatch) => {
dispatch({ type: 'START_FETCHING_RECIPES_REQUEST' });
fetch(RECIPES_URL)
.then(response =>{ return response.json()})
.then(recipes => dispatch({ type: 'Get_Recipes', recipes }));
};
}
This is where I am trying to render the Recipe component from the get request
import React, {Component} from 'react';
// import { getRecipes } from '../actions/getRecipes.js';
import Recipe from './Recipe.js'
class RecipeList extends Component {
// componentDidMount(){
// getRecipes()
// }
render() {
return (
<div>
{this.props.recipes.map(recipe => (<Recipe recipe={recipe} key={recipe.id} />))}
</div>
)
}
}
export default RecipeList;
Edit: Added reducer
switch(action.type){
case 'Add_Recipe':
const recipe = {
name: action.name,
ingredients: action.ingredients,
chef_name: action.chef_name,
origin: action.origin,
category: action.category
}
return{
...state,
recipes: [...state.recipes, recipe],
}
case 'START_FETCHING_RECIPES_REQUEST':
return {
...state,
recipes: [...state.recipes],
requesting: true
}
case 'Get_Recipes':
return {
...state, recipes: action.recipes,
requesting: false
}
default:
return state
}
}
How can I correct this to make it work?
Issue
You are not passing the recipes to the RecipeList component that were fetched and presumably stored in state, and fed back to the UI via RecipeContainer.
Solution
Pass the recipe state from RecipeContainer to RecipeList as a prop. and then render/map the recipes from props.
RecipeContainer
class RecipeContainer extends Component{
componentDidMount() {
getRecipes();
}
render() {
return (
<div>
<RecipeInput postRecipes={this.props.postRecipes} />
<RecipeList getRecipes={this.props.recipes} /> // <-- pass recipe state
</div>
)
}
}
const mapStateToProps = state => ({
recipes: state.recipes,
});
const mapDispatchToProps = dispatch => {
return {
postRecipes: (recipe) => dispatch(postRecipes(recipe)),
getRecipes: () => dispatch(getRecipes())
}
};
RecipeList
class RecipeList extends Component {
render() {
const { recipes } = this.props;
return (
<div>
{recipes.map(recipe => (
<Recipe recipe={recipe} key={recipe.id} />
))}
</div>
);
}
}
The actual solution to this was I needed to have an explicit return in my mapStateToProp function.
Eg.
const mapStateToProp = state =>{
return {
recipes: state.recipes
}
}

Passing a state value in functional component in React

I am trying to use promise tracker. I used react-promise-tracker package.
Below the code of my component:
import React from "react";
import { usePromiseTracker } from "react-promise-tracker";
import Spinner from "./Spinner";
const LdngIndicator = (props) => {
const { promiseInProgress } = usePromiseTracker();
return promiseInProgress && <Spinner />;
};
export default function LoadingIndicator() {
return <LdngIndicator />;
}
parent.js
import React, { Component } from "react";
import { trackPromise } from "react-promise-tracker";
import LoadingIndicator from "./LoadingIndicator";
export default class App extends Component {
constructor() {
super();
this.state = {
randomResponse: "",
};
}
apifunc = () => {
trackPromise(
fetch(
"https://****.rapidapi.com/random",
{
method: "GET",
headers: {
accept: "application/json",
"x-rapidapi-key": process.env.REACT_APP_KEY,
"x-rapidapi-host": "host.rapidapi.com",
},
}
)
.then((res) => res.json())
.then((res) => {
this.setState({
randomResponse: res,
});
})
.catch((err) => {
console.error(err);
})
);
};
handleSubmit = (e) => {
e.preventDefault();
this.apifunc();
};
render() {
return (
<div className="wrapper">
<form className="jokesForm" onSubmit={this.handleSubmit}>
<label>Get a new joke</label>
<input type="submit" value="Go!"></input>
</form>
<main>
{<LoadingIndicator /> ? <p>True</p> : <p>false</p>}
</main>
</div>
);
}
}
I can run this without any issues. I would like to get boolean value of the promiseInProgress in my parent component.
promiseInProgress changes as I make requests.
What is the best way to send this as props?
I read https://reactjs.org/docs/components-and-props.html as well as different questions on stack overflow but I was not able to find an answer to my quesiton.
I appreciate any help.
you didn't show us your parent component though so let's assume its a functional component
//parent.jsx
import react, { useState } from 'react'
import Loader from 'loader.jsx'
const ParentComp = () => {
const [state, setState] = useState(false)
return <>
<Loader setState={setState} setState={setState} />
<span> {`state: ${state}`} <span/>
</>
}
export default ParentComp
//loader.jsx
import React from "react";
import { usePromiseTracker } from "react-promise-tracker";
import Spinner from "./Spinner";
const LdngIndicator = () => {
const { promiseInProgress } = usePromiseTracker();
return promiseInProgress && <Spinner />;
};
export default function LoadingIndicator({state, setState}) {
return <>
<button onClick={() => setState(!state)}>click</button>
<LdngIndicator />
</>
}
you get the idea? what you can easily do is to pass setState to child component and modify it from the child

solve:Expected an assignment or function call and instead saw an expression no-unused-expressions

hey i am new in the field and want to display the state using the map and i am not able to do so
and there is no problem in the api call through axios so ignore it
my code is
import React, { Component } from 'react';
import axios from 'axios';
const url ='https://www.reddit.com/r/space.json';
class Apicall extends Component {
state={
posts:[],
subr:'space'
};
componentDidMount(){
this.getReddit();
}
getReddit=async()=>{
console.log('getredddit called sir ');
try {
let response=await axios.get(`https://www.reddit.com/r/${this.state.subr}.json`);
let posts=response.data.data.children.map(obj=>obj.data)
this.setState({posts:posts},()=>{console.log(this.state.posts);
})
} catch (error) {console.log(error);}}
render() {
let controlItems=this.state.posts.map(post=>{<h1 id={post.id}>{post.title}</h1>});
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>);
}
}
export default Apicall;
You were iterating wrong on your data. response.data.data.children should be replaced with response.data.children. Implicit return of et controlItems=this.state.posts.map(post=>{{post.title}}); is also wrong.
import React from "react";
import "./styles.css";
export default function App() {
return (
<div className="App">
<Apicall />
</div>
);
}
class Apicall extends React.Component {
state = {
posts: [],
subr: "space"
};
componentDidMount() {
this.getReddit();
}
getReddit = async () => {
console.log("getredddit called sir ");
try {
let response = await fetch(
`https://www.reddit.com/r/${this.state.subr}.json`
);
response = await response.json();
console.log(response);
let posts = response.data.children.map(obj => obj.data);
this.setState({ posts: posts }, () => {
console.log(this.state.posts);
});
} catch (error) {
console.log(error);
}
};
render() {
let controlItems = this.state.posts.map(post => (
<h1 id={post.id}>{post.title}</h1>
));
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>
);
}
}

Resources