fire onClick function from child component - reactjs

TLDR: How would i retrieve the console.log from the child component
after url has been submitted
I want to be able to get the response data from the child component after a url has been submitted. How would i be able to do this ?
In other words how i be able to fire the onClick function after a url has been submitted ?
code sandbox
https://codesandbox.io/s/cool-feather-fjkv6
Parent
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import Child from './Child';
class Parent extends Component {
constructor(props){
super(props);
this.state = {
url:'',
outputUrl:''
}
}
onChange = (e) => {
e.preventDefault();
this.setState({
url: e.target.value
})
}
onSubmit = (e) => {
e.preventDefault();
console.log(this.state.url)
}
render(){
return (
<div className="App">
<form onSubmit={this.onSubmit}>
<input type="text" onChange={this.onChange} value={this.state.url} placeholder="Enter url " />
<button type="submit" >Submit</button>
</form>
{/* if have url else enter test url */}
<Child url={this.state.url} method={'GET'} />
</div>
);
}
}
export default App;
How would i retrieve the console.log from the child component after url has been submitted ? I'm slightly confused. Sorry if this is looks confusing.
Child
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
class Child extends Component {
constructor(props){
super(props);
this.state = {
data:[]
}
}
// componentDidUpdate or try this
onClick(){
const url = `${this.props.url}`;
if(this.props.method === "GET"){
axios.get(url).then( res => {
this.setState({
data: res.data
})
console.log(this.state.data)
})
}
else if(this.props.method === "POST"){
axios.get(url).then( res => {
this.setState({
data: res.data
})
console.log(this.state.data)
})
}
}
render(){
return (
null
);
}
}
export default Child;

Please! see render method on Child Component
class Child extends Component {
static onClick() {
// do something
}
constructor(props) {
super(props);
this.state = {
data: []
};
}
// componentDidUpdate or try this
onClick = e => {
e.preventDefault();
const url = `${this.props.url}`;
if (this.props.method === "GET") {
axios.get(url).then(res => {
this.setState({
data: res.data
});
console.log(this.state.data);
});
} else if (this.props.method === "POST") {
axios.get(url).then(res => {
this.setState({
data: res.data
});
console.log(this.state.data);
});
}
};
render() {
return <div onClick={this.onClick}>Click Me</div>;// <------
}
}

Related

React API data not showing up in JSX

[enter link description here][1]I am fetching API in react. I am able to see data in console but it is not appearing in JSX. I want to see Data id, name and value. But it is not appearing in browser.
[1]: https://codesandbox.io/s/late-thunder-456qp?file=/src/App.js
import React from 'react';
import axios from 'axios'
import './App.css';
class Main extends React.Component {
constructor(props) {
super(props)
this.state = {
users: [],
error: ''
}
}
componentDidMount(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then( response => {
console.log(response);
this.setState({users: response.data})
})
.catch(error =>{
console.log(error);
})
}
render() {
const { users } = this.state
return (
<div>
<h2> Main Page</h2>
<p class="para-text"> Data from API</p>
{
users.length ?
users.map(post => <div key ={ users.id }> { users.name} </div>) : null
}
</div>
);
}
}
export default Main;
when mapping you named the key to your map as post and therefore when displaying them in jsx you must refer to that key
attached is a forked version of your sandbox https://codesandbox.io/s/late-thunder-456qp?file=/src/App.js
import "./styles.css";
import React from "react";
import axios from "axios";
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
error: ""
};
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
this.setState({ users: response.data });
})
.catch((error) => {
console.log(error);
});
}
render() {
const { users } = this.state;
return (
<div>
<h2> Main Page</h2>
<p class="para-text"> Data from API</p>
{users.length > 0
? users.map((post) => <div key={post.id}> {post.name} </div>)
: null}
</div>
);
}
}
export default Main;

Unable to update state on axios response in a class react js

I'm unable to update the state using the axios response in a class component. It works just fine with function based components. Could somebody please point out what is causing this issue. I'm new to react and tried most of the possible answers out there.
code :
import React, { Component } from "react";
import "./Table.css";
import { Button } from "./Button";
import { Table } from "react-bootstrap";
import axios from "axios";
import Example from "./Progress";
class Tables extends Component {
constructor(props) {
super(props);
this.state = {
submitted: false,
task_id: "",
};
this.handlesubmit = this.handlesubmit.bind(this);
}
handlesubmit(event) {
var self = this;
event.preventDefault();
axios({
method: "post",
url: "http://127.0.0.1:8000/api/test/",
data: {
project_name: "test",
},
}).then(function (response) {
console.log(response.data.task_id); //prints taskid (12345678)
self.setState({
task_id: response.data.task_id,
});
console.log(self.task_id); //prints undefined
});
this.setState({ submitted: true }); //works fine, state is set to true
console.log(this.task_id); //prints undefined
}
render() {
let modal;
let task_id = this.state.task_id;
let submitted = this.state.submitted;
if (submitted === true) {
modal = <Example pro="test" task={task_id} />;
}
return (
<div className="table-div">
<Button
buttonStyle="btn--secondary"
buttonSize="btn--small--opt"
onClick={this.handlesubmit}
>
test
</Button>
{modal}
</div>
);
}
}
export default Tables;
You should update your state inside then when the axios call succeeds:
handleSubmit(event) {
event.preventDefault();
axios({...})
.then((response) => {
this.setState({
task_id: response.data.task_id,
submitted: true
})
})
.catch((error) => { /* handle errors appropriately */ })
}
Then, inside your render method, make sure that both task_id and submitted have appropriate values before rendering the modal:
render() {
const { task_id, submitted } = this.state
const modal = submitted && task_id !== ""
? <Example pro="test" task={task_id} />
: null // don't render anything
return (
<div className="table-id">
<Button ...>test</Button>
{modal}
</div>
)
}

React HOC with Router not finding page

Hi I am working on a react app with Routing and HOC. I expect to see a page but i get page not found when i know the page is there.
in componentDidMount this.setState, data is shown as undefined but in the HOC wrapper i see the data arrive from the server.
Before I wrapped the page in HOC i could see it rendering content so I know the content exists.
Here is my Page component which is being called via a Route :
import React, { Component } from "react";
import WithBackend from "./WithBackend";
class Page extends Component {
constructor(props) {
super(props);
this.state = { model: null };
}
render() {
if (this.state.model != null) {
return (
<div className="container">
<div className="row">
<div className="col-md">
<h1>{this.state.model.title}</h1>
</div>
</div>
</div>
);
} else {
return (
<div>
<h2>Home</h2>
</div>
);
}
}
componentDidMount() {
const data = this.props.getPage("1");
console.log(data);
this.setState({
model: data,
});
}
}
export default WithBackend(Page);
Here is the HOC component WithBackend: I am not sure if i should be setting the state on this class on in the class that is being wrapped.
When i debug the code in the getPage method, in the setState part i see the data being populated from the backend server.
import React from "react";
import ContentService from "./ContentService";
const WithBackend = (WrappedComponent) => {
class HOC extends React.Component {
constructor() {
super();
this.contentService = new ContentService();
this.getPage = this.getPage.bind(this); // <-- Add this
}
getPage(id) {
this.contentService
.getPage(id)
.then((response) => response.json())
.then((data) => {
this.setState({ model: data });
})
.catch((e) => {
console.log(e);
});
}
render() {
return <WrappedComponent getPage={this.getPage} {...this.props} />;
}
}
return HOC;
};
export default WithBackend;
and here is the contentService which only returns a promise:
class ContentService {
pageUrl = process.env.REACT_APP_BASE_URL + "/pages/";
getPage(id) {
const path = this.pageUrl + id;
const fetchPromise = fetch(path, {
method: "GET",
});
return Promise.resolve(fetchPromise);
}
}
export default ContentService;
Could anyone please advice what i am doing wrong?
Thanks in advance.
getPage is an asynchronous method, that should return a promise:
getPage(id) {
return this.contentService
.getPage(id)
.then((response) => response.json())
.catch((e) => {
console.log(e);
});
}
And then
componentDidMount() {
this.props.getPage("1").then(model => this.setState({ model }));
}

Pass props to different components in react

Just having troubles, sorry for the noob question, but i can't seem to log the props results in the DisplayData.js file. I am trying to pass the SearchStockResult state to the DisplatData.js file... I have tried to console log the data property with no luck. Not to sure what is going on. Excuse the naming conventions as I had just changed it from a stock search to a crypto search.
import React, { Component } from 'react'
import DisplayData from './DisplayData';
export default class stockSearch extends Component {
state = {
searchResult: '',
}
componentDidMount = () => {
fetch(`https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,IOT&tsyms=USD`)
.then((response) => response.json())
.then(data => {
this.setState({ searchResult: data });
console.log(this.state.searchResult);
});
}
render() {
const {data} = this.state;
return (
<form>
<label>
Name:
<input type="text" name="query" />
</label>
<button>Search Crypto</button>
<DisplayData results={data} />
</form>
)
}
}
import React, { Component } from 'react'
export default class DisplayData extends Component {
dataResults = (props) => {
console.log('from data results', props.results);
}
render() {
return (
<div>
</div>
)
}
}
Make few corrections:
State update is async. So pass a call back function if you want to print it
in StockSearch component, you need to destructure searchResult from state (not data)
In DisplayData component use this.props. Also call your function(dataResults) in render method so that it is called and rendered
Working copy of your code is here
StockSearch Component
import React, { Component } from "react";
import DisplayData from "./DisplayData";
export default class StockSearch extends Component {
state = {
searchResult: ""
};
componentDidMount = () => {
fetch(
`https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,IOT&tsyms=USD`
)
.then(response => response.json())
.then(data => {
this.setState({ searchResult: data }, () => {
console.log("api result", this.state.searchResult);
});
});
};
render() {
const { searchResult } = this.state;
return (
<form>
<label>
Name:
<input type="text" name="query" />
</label>
<button>Search Crypto</button>
<DisplayData results={searchResult} />
</form>
);
}
}
DisplayData Component
import React, { Component } from "react";
export default class DisplayData extends Component {
dataResults = () => {
console.log("from data results", this.props.results);
};
render() {
this.dataResults() // just to print
return <div>{return <div>{JSON.stringify(this.props.results)}</div>;}</div>;
}
}

request data, pass it to another component and return it in react

I want to display search results on a page. My idea was to make a submit that sends a request to the server. After receiving the data I iterate through it and call a function to process it in another component which should render processed data back to the parent component. Unfortunately no data rendered in the search component and no errors were given to debug.
The main problem right now is that no data is returned from SearchResults; also I'm not sure if the data is received in that component.
import React, { Component } from "react";
import axios from "axios";
import SearchResults from "./SearchResults";
export default class SearchComponent extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
query: "",
searchresults: []
};
}
submitSearchResults(searchresults) {
return this.state.searchresults.map(function(object, i) {
return <SearchResults obj={object} key={i} />;
});
}
onSubmit(e) {
e.preventDefault();
axios
.get("http://localhost:4200/serverport/spotify/" + this.state.song)
.then(res => {
const searchresults = res.data;
for (var key in searchresults) {
if (searchresults.hasOwnProperty(key)) {
for (var i = 0; i < searchresults[key].items.length; i++) {
this.submitSearchResults(searchresults[key].items[i]);
}
}
}
});
}
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input
type="text"
value={this.state.query}
onChange={this.onChangeSong}
/>
<input value="search" type="submit" />
</form>
<div>{this.submitSearchResults()}</div>
</div>
);
}
}
This is the code that requests the data from server. I removed some irrelevant code to make it more readable.
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
class SearchResults extends Component {
constructor(props) {
super(props);
}
render() {
return <div>works</div>;
}
}
export default SearchResults;
This is the file where the data is supposed to be processed. I only render "works" for debugging.
Instead of calling the function that renders your search result JSX when the request is complete, you can set the searchresults in the state and the component will re-render automatically.
Example
const axios = {
get: () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({ data: [{ text: "foo" }, { text: "bar" }] });
}, 1000);
});
}
};
class SearchComponent extends React.Component {
state = {
song: "",
searchresults: []
};
submitSearchResults(searchresults) {
return this.state.searchresults.map(function(object, i) {
return <SearchResults obj={object} key={i} />;
});
}
onSubmit = e => {
e.preventDefault();
axios
.get("http://localhost:4200/serverport/spotify/" + this.state.song)
.then(res => {
const searchresults = res.data;
this.setState({ searchresults });
});
};
onChangeSong = e => {
this.setState({ song: e.target.value });
};
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input
type="text"
value={this.state.song}
onChange={this.onChangeSong}
/>
<input value="search" type="submit" />
</form>
<div>{this.submitSearchResults()}</div>
</div>
);
}
}
class SearchResults extends React.Component {
render() {
return <div>{this.props.obj.text}</div>;
}
}
ReactDOM.render(<SearchComponent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Resources