How can I pass an object ID from mapped array to backend? - javascript

I want to pass the ID of an object to the backend. The objects are mapped from the array and there should be a separate button for each one so that the ID of each individual object can be pass to the backend.
The communication between backend and frontend works. The only problem is that the ID is not sent to the backend when the submit button is clicked. If I would now work with an OnChange and enter the ID myself in the text field, then it would work without any problems.
Does somebody has any idea?
Here my code:
import React from 'react';
import {format} from "date-fns-tz";
import {Link} from "react-router-dom";
import MailQueueDataService from "../services/mail_queue.service";
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
mailqueues_unsent: {},
loading: false
}
this.parentClassFunction = this.parentClassFunction.bind(this);
}
parentClassFunction = () => {
console.log("TEST");
event.preventDefault();
const url = "/api/v1/mail_queues/authorize_mail_queue";
const { id } = this.state;
const body = {
id,
};
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "POST",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then(response => this.props.history.push(window.close()))
.catch(error => console.log(error.message));
}
render() {
return (
<div>
<Child
parentClassFunction={this.parentClassFunction}
/>
</div>
)
}
}
class Child extends React.Component{
constructor(props){
super(props);
this.state = {
mail_queues_unsent: [],
loading: false
}
}
onClickSubmitButton = () =>{
this.props.parentClassFunction()
};
retrieveMailQueues() {
MailQueueDataService.getAll().then(response => {
if (this._isMounted)
this.setState({
mail_queues_unsent: response.data.mailqueues_unsent,
loading: false}
)
}).catch(e => {
console.log(e)
})
}
componentDidMount() {
this._isMounted = true;
this.setState({loading: true})
this.retrieveMailQueues();
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
if (this.state.loading) {
return <div className="col text-center"> Lade Unautorisierte Mails... </div>;
} else {
const {mail_queues_unsent} = this.state;
const allMailsUnsent = mail_queues_unsent.map((mailqueues_unsent, index) => (
<div className="col">
<div key={index}>
<h4><b>Empfänger:</b>{mailqueues_unsent.company_name}</h4>
<b>Datum Versandfreigabe:</b>
{format(new Date(mailqueues_unsent.created_at), 'dd.MM.yyyy hh:mm')}
<p><b>Anzahl der Tests:</b> {mailqueues_unsent.trials_count}</p>
<b>Tests:</b>
<p>{mailqueues_unsent.trials.map(trial => <Link to={"/trials/" + trial.id}>
<p>{trial.certificate_number}</p></Link>)}</p>
<form onSubmit={this.parentClassFunction}>
<label htmlFor="id"></label>
<input
type="text"
name="id"
id="id"
value={mailqueues_unsent.id}
className="form-control"
onChange={this.onChange}
/>
<button onClick={this.onClickSubmitButton.bind(this)}>CLICK</button>
</form>
</div>
</div>
));
const noMailQueues = (
<div>
<h4>
Kein Unautorisierte Mails vorhanden.
</h4>
</div>
);
return (
<div>
{mail_queues_unsent.length > 0 ? allMailsUnsent : noMailQueues}
</div>
)
}
}
}
export default Parent;

Since you are calling a function that is passed as prop from the parent, inside the child component you should call it on submit like this (its not this but this.props):
onSubmit={this.props.parentClassFunction}

Related

React class component state value not updating

I am new to react js. I am learning it by creating a simple app. I tried to create a simple weather app using react class component. All working fine but the result stored in a state variable is not printing in the template. I can see the API response in the console and then store the result on the 'currWeatherRes' state variable which is not showing in the template (Location is always blank)
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(){
super();
this.state = {
cityName: "",
currWeatherRes: {}
}
}
handleSubmit = (event) => {
event.preventDefault();
alert(`The name you entered was:`+ this.state.cityName);
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
console.log(response)
this.setState({
currWeatherRes: response
})
//return response.json();
});
}
handleChange = (event) => {
this.setState({cityName:event.target.value});
}
render() {
return (
<div className="weather-app">
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.cityName} onChange={this.handleChange} placeholder="Enter City"/>
<button type="submit" value="Submit">Submit</button>
</form>
{(typeof this.state.currWeatherRes.main != "undefined") ? (
<div className="weather-details">
<div className="weather-location">
<div className="location">Loctaion: {this.state.currWeatherRes.name}</div>
</div>
</div>
):('')}
</div>
);
}
}
export default App;
The problem was not related to react but the way you handled API call.
Fix:
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
return response.json();
}).then((res) => {
this.setState({
currWeatherRes: res
})
});
Working code:
import React, { Component } from 'react';
class App extends Component {
constructor(){
super();
this.state = {
cityName: "",
currWeatherRes: {}
}
}
handleSubmit = (event) => {
event.preventDefault();
alert(`The name you entered was:`+ this.state.cityName);
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
return response.json();
}).then((res) => {
this.setState({
currWeatherRes: res
})
});
}
handleChange = (event) => {
this.setState({cityName:event.target.value});
}
render() {
console.log(this.state.currWeatherRes)
return (
<div className="weather-app">
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.cityName} onChange={this.handleChange} placeholder="Enter City"/>
<button type="submit" value="Submit">Submit</button>
</form>
{(typeof this.state.currWeatherRes.main != "undefined") ? (
<div className="weather-details">
<div className="weather-location">
<div className="location">Loctaion: {this.state.currWeatherRes.name}</div>
</div>
</div>
):('')}
</div>
);
}
}
export default App;

display button upon typing input react

I want to be able to type into my input fields, and then have a button show up beside it upon typing that says submit edit. right now, I have a button that always is there, but I want it to only show up upon typing. this is all in react btw. so far, I have tried jquery, but react doesn't like it.
here's the whole page, to avoid any confusion of what I am doing and where my stuff is located.
import React, { Component } from "react";
import axios from "axios";
import "../styles/TourPage.css";
class TourPage extends Component {
constructor(props) {
super(props);
this.state = {
myData: [],
isLoading: true,
};
}
componentDidMount() {
axios
.get("/getResults")
.then((res) => {
this.setState({
myData: res.data
});
})
.catch((error) => {
// Handle the errors here
console.log(error);
})
.finally(() => {
this.setState({
isLoading: false
});
});
}
deleteById = (id) => {
console.log(id)
axios
.post(`/deleteDoc`, {id: id} )
.then(() => {
console.log(id, " worked")
window.location = "/tour"
})
.catch((error) => {
// Handle the errors here
console.log(error);
})
}
editById = (id, siteLocation, Services, cnum) => {
console.log(id, siteLocation, Services, cnum)
axios
.post(`/editDoc`, JSON.stringify({id: id, location: siteLocation, Services: Services, cnum: cnum}),{
headers: {
"Content-Type": "Application/json"
}
} )
.then(() => {
console.log(id, " worked")
window.location = "/tour"
})
.catch((error) => {
// Handle the errors here
console.log(error);
})
}
render() {
// You can handle the loader part here with isLoading flag. In this case No data found will be shown initially and then the actual data
let { myData, isLoading } = this.state;
return (
<table id="customers">
<tr>
<th>siteLocation</th>
<th>Services</th>
<th>cnum</th>
</tr>
{myData.length > 0
? myData.map(({ location, Services, cnum, _id }, index) => (
<tr key={index}>
<td><input type="text" placeholder={location} name="location" id="location" /> </td>
<td><input type="text" placeholder={Services} name="Services" id="Services" /> </td>
<td><input type="text" placeholder={cnum} name="cnumhide" id="cnumhide" /> </td>
<td><input type="hidden" placeholder={cnum} name="cnum" id="cnum" /> </td>
<button
onClick={(e) => {
e.preventDefault();
this.deleteById(_id);
}}
disabled={isLoading}
>
Delete
</button>
<button
onClick={(e) => {
e.preventDefault();
var siteLocation = document.getElementById('location').value
var Services = document.getElementById('Services').value
var cnum = document.getElementById('cnum').value
this.editById(_id, siteLocation, Services, cnum)
}}
>
Submit Edit
</button>
</tr>
))
: "No Data Found"}
</table>
);
}
}
const script = document. createElement("script"); $('input').keyup(function(){
if($.trim(this.value).length > 0)
$('#location').show()
else
$('#location').hide()
});
export default TourPage;
thanks 4 the help in advance.
You can use onfocus() in the text element. If you want to hide the button, use onfocusout() or in case if you want to track only after input has changed, use onchange() event
...
//class function
onTyping =()=>{
this.setState({
showSubmit:true
})
}
...
//render part
render(){
...
//input which you want to track typing
<input type="text" onfocus={()=>this.onTyping()} placeholder={location} name="location" id="location" />
...
//element submit button
{this.state.showSubmit && <button
onClick={(e) => {
e.preventDefault();
var siteLocation = document.getElementById('location').value
var Services = document.getElementById('Services').value
var cnum = document.getElementById('cnum').value
this.editById(_id, siteLocation, Services, cnum)
}}
>
Submit Edit
</button>}
...
Here is an example that helps you,
const {
useState
} = React;
const Test = () => {
const [show, setShow] = useState(false);
const handleChange = (event) => {
if (event.target.value.length > 0)
setShow(true);
else
setShow(false)
}
return ( <div>
<input type = "text"
onChange = {
(event) => handleChange(event)
}/>
{show && < button > Submit changes now! </button>}
</div>
)
}
ReactDOM.render( < Test / > ,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
There is a way to avoid jquery and continue using your react class component to achieve this.
Map over state.myData to render each item with an input and a button.
Use the array index with the input's onChange event callback to add the inputValue into the correct array item's object within state.
Use the array index with the button's onClick event callback to get the item from state.myData before sending it to the server.
If there is an inputValue for the item, you can conditionally render the button.
import React, { Component } from "react";
import axios from "axios";
class TourPage extends Component {
constructor(props) {
super(props);
this.state = {
myData: [],
isLoading: true
};
}
componentDidMount() {
axios
.get("https://rickandmortyapi.com/api/character")
.then((res) => {
this.setState({
myData: res.data.results
});
})
.finally(() => {
this.setState({
isLoading: false
});
});
}
handleChangeInput = ({ target }, index) => {
const newData = [...this.state.myData];
newData[index].inputValue = target.value;
this.setState({
myData: newData
});
};
handleSubmitEdit = (index) => {
const item = this.state.myData[index];
// submit the edit to the api
console.log(
`Clicked on 'submit edit' for ${item.name} with value ${item.inputValue}`
);
};
render() {
let { myData, isLoading } = this.state;
if (isLoading) {
return "loading...";
}
return (
<div>
{myData.map(({ name, status, species, inputValue }, index) => {
return (
<div key={index}>
<p>{`${name} - ${species} - ${status}`}</p>
<input
type="text"
onChange={(e) => this.handleChangeInput(e, index)}
value={inputValue || ""}
/>
{inputValue && (
<button onClick={() => this.handleSubmitEdit(index)}>
Submit Edit
</button>
)}
</div>
);
})}
</div>
);
}
}
export default TourPage;
If you wanted to have an input per field within each row, you could make some small changes and save your edits to the item's state within a nested object.
Then you could check if there was anything inside that row's edits object to conditionally show the submit button per row.
import React, { Component } from "react";
import axios from "axios";
import isEmpty from "lodash.isempty";
import pick from "lodash.pick";
class TourPage extends Component {
constructor(props) {
super(props);
this.state = {
myData: [],
isLoading: true
};
}
componentDidMount() {
axios
.get("https://rickandmortyapi.com/api/character")
.then((res) => {
this.setState({
// here we create an empty 'edits' object for each row
myData: res.data.results.map((d) => ({
...pick(d, ["name", "status", "species"]),
edits: {}
}))
});
})
.finally(() => {
this.setState({
isLoading: false
});
});
}
handleChangeInput = ({ target }, index) => {
const newData = [...this.state.myData];
const { value, name } = target;
newData[index].edits[name] = value;
this.setState({
myData: newData
});
};
handleSubmitEdit = (index) => {
const item = this.state.myData[index];
// submit the edit to the api
console.log(`Clicked on 'submit edit' for ${item.name} with edits:`);
console.log(item.edits);
console.log("Updated item: ");
const { edits, ...orig } = item;
const newItem = { ...orig, ...edits };
console.log(newItem);
// Once saved to api, we can update myData with newItem
// and reset edits
const newData = [...this.state.myData];
newData[index] = { ...newItem, edits: {} };
this.setState({
myData: newData
});
};
showButton = (index) => {
const { edits } = this.state.myData[index];
return !isEmpty(edits);
};
render() {
let { myData, isLoading } = this.state;
if (isLoading) {
return "loading...";
}
return (
<table>
<tbody>
{myData.map((row, index) => {
const { edits, ...restRow } = row;
return (
<tr key={index}>
{Object.keys(restRow).map((col) => {
return (
<td>
<label>
{col}:
<input
name={col}
value={edits[col] || restRow[col]}
onChange={(e) => this.handleChangeInput(e, index)}
/>
</label>
</td>
);
})}
<td>
{this.showButton(index) && (
<button onClick={() => this.handleSubmitEdit(index)}>
Submit Edit
</button>
)}
</td>
</tr>
);
})}
</tbody>
</table>
);
}
}
export default TourPage;

React.js translate component not showing on the browser

I am trying to create a web app in which user search for a word using 'Form' component and then the result is fetched from an API and then passed to 'translate' component, but my 'translate' component is not showing in the browser.
form.jsx
import React from "react";
import "./form.scss";
import Translate from "./translate"
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
term: "",
getdata: []
}
}
handleChange = (e) => {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value });
};
componentDidMount() {
}
submit = (e) => {
e.preventDefault();
const { term } = this.state;
const rawUrl="https://mashape-community-urban-dictionary.p.rapidapi.com/define?term="+term;
const url=rawUrl;
fetch(url, {
"method": "GET",
"headers": {
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com",
"x-rapidapi-key": "c8cb6b8cccmshc02b57f0b5a8c98p1516cdjsnb64d72a5ad33"
}
})
.then(response => {
return response.json();
})
.then(data=>{
this.setState({getdata:[data.list]});
console.log(this.state.getdata);
})
.catch(err => {
console.log(err);
});
}
render() {
const translate=this.state.getdata.map(item => (<Translate word={item.word} definition={item.definition} />))
return (
<div class="full">
{translate}
<div class="searchForm">
<form>
<input type="text" name="term" value={this.state.term} placeholder="Enter a word here" onChange={this.handleChange}></input><button onClick={this.submit}>Search</button>
</form>
</div>
</div>
);
}
}
export default Form;
translate.jsx
import React from "react";
import "./translate.css";
class Translate extends React.Component {
render() {
return (
<div class="all">
<div class="single">
<div class="word">
{this.props.word}
</div>
<div class="def">
{this.props.definition}
</div>
</div>
</div>
);
}
}
export default Translate;
Can anyone solve this error.
I am stuck on this for a long time.
The issue is that you're saving the array returned by the API call within another array this.setState({getdata:[data.list]});. This is making it difficult to parse. Below is a working example which has been simplified due to limited access to your css files:
Form.js
import React from "react";
import Translate from "./Translate";
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
term: "",
getdata: []
};
}
handleChange = (e) => {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value });
};
componentDidMount() {}
submit = (e) => {
e.preventDefault();
const { term } = this.state;
const rawUrl =
"https://mashape-community-urban-dictionary.p.rapidapi.com/define?term=" +
term;
const url = rawUrl;
fetch(url, {
method: "GET",
headers: {
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com",
"x-rapidapi-key": "c8cb6b8cccmshc02b57f0b5a8c98p1516cdjsnb64d72a5ad33"
}
})
.then((response) => {
return response.json();
})
.then((data) => {
console.log("DATA", data.list);
this.setState({ getdata: data.list });
})
.catch((err) => {
console.log(err);
});
};
render() {
const translate = this.state.getdata.map((item) => (
<Translate
word={item.word}
definition={item.definition}
key={item.defid}
/>
));
return (
<div>
<div>
<form>
<input
type="text"
name="term"
value={this.state.term}
placeholder="Enter a word here"
onChange={this.handleChange}
></input>
<button onClick={this.submit}>Search</button>
</form>
{translate}
</div>
</div>
);
}
}
export default Form;
Translate.js
import React from "react";
export default function Translate(props) {
const { word, definition } = props;
return (
<div>
<div>
<div>{word}</div>
<div>{definition}</div>
</div>
</div>
);
}

Changing parent state after updating childs prop component in React?

I'm newish to react. I have a fetch call in my App Component that I assign to a state. I pass that state as a prop along with a function to make a post to a child component. In my child component you can post/delete to alter the props, currently don't have a push() to add the new contact/prop. Is there a way to alter the parent component's state after I change the childs props? is there a better way to do this?
I'm trying to get the post action to update the state on the App.
App code
class App extends Component {
constructor() {
super();
this.state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
}
componentDidMount() {
var request = new Request('http://localhost:3000/', {
method: "GET",
});
fetch(request)
.then((res) => {
res.json()
.then((data) => {
this.setState({
contacts: data.rows
})
})
})
}
toggleModal() {
this.setState({
modalIsOpen: ! this.state.modalIsOpen
})
}
addContact(event) {
this.toggleModal()
event.preventDefault();
let contactData = {
first: this.refs.first.value,
last: this.refs.last.value,
phone: this.refs.phone.value,
email: this.refs.email.value,
};
var request = new Request('http://localhost:3000/add', {
method: "POST",
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify(contactData)
});
console.log(this.state)
fetch(request)
.then((res) => {
res.json()
.then((data) => {
})
})
.catch((err) => {
console.log(err)
})
}
render() {
return (
<Container>
{console.log(this.state)}
<AddContact addContact={this.addContact} contacts={this.state.contacts} />
<ContactList contacts={this.state.contacts} />
<Contacts contacts={this.state.contacts}/>
</Container>
);
}
}
export default App;
Child component
class AddContact extends Component {
constructor(props) {
super(props);
this.state = {
contacts: [],
modalIsOpen: false,
}
}
toggleModal() {
this.setState({
modalIsOpen: ! this.state.modalIsOpen
})
}
render() {
return(
<Container>
<div className='header'>
<h1>
My Contacts
<button className='addContactButton' onClick={this.toggleModal.bind(this)}>+</button>
</h1>
<hr />
</div>
<Modal isOpen={this.state.modalIsOpen}>
<form ref='addContact' >
<div className='addContactHeader'>
<button className='saveButton' onClick={this.props.addContact.bind(this)}>Save</button>
<button className='cancelButton' onClick={this.toggleModal.bind(this)}>Cancel</button>
</div>
<div id="circle">
Add Photo
</div>
<div className="inputFields">
<div className='nameInputs'>
<input type='text' ref='first' placeholder='first name' />
<input type='text' ref='last' placeholder='last name' />
</div>
<div className='extraInputs' >
<input type='text' ref='phone' placeholder='phone' />
<input type='text' ref='email' placeholder='email' />
</div>
</div>
</form>
</Modal>
</Container>
)
}
}
Thanks for your time
You could use a callback function in order to update the state on the parent component (Another approach would be to use Redux updating the value in the Store, that way both components could have access to the value), here's how you could use the callback (With a little bit of ES6 refactor):
App:
class App extends Component {
state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
componentDidMount() {
let request = new Request('http://localhost:3000/', {
method: "GET",
});
fetch(request)
.then((res) => {
res.json()
.then((data) => { this.setState({ contacts: data.rows }) })
})
}
toggleModal = () => {
this.setState({ modalIsOpen: ! this.state.modalIsOpen })
};
addContact = event => {
this.toggleModal()
event.preventDefault();
let contactData = {
first: this.refs.first.value,
last: this.refs.last.value,
phone: this.refs.phone.value,
email: this.refs.email.value,
};
let request = new Request('http://localhost:3000/add', {
method: "POST",
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify(contactData)
});
fetch(request)
.then((res) => {
res.json()
.then((data) => {
})
})
.catch((err) => {
console.log(err)
})
};
changeContacts = (newData) => {
this.setState({ contacts: newData });
};
render() {
const { contacts } = this.state;
return (
<Container>
<AddContact
addContact={this.addContact}
contacts={contacts}
onChildAction={this.changeContacts}
/>
<ContactList contacts={contacts} />
<Contacts contacts={contacts}/>
</Container>
);
}
}
export default App;
AddContacts:
class AddContact extends Component {
state = {
contacts: [],
modalIsOpen: false,
}
toggleModal = () => {
this.setState({ modalIsOpen: ! this.state.modalIsOpen })
};
// Here is where you'll send the info for the change of the prop
changeProp = e => {
const { onChildAction } = this.props;
onChildAction('Your new state/prop value here')
addContact(e);
};
render() {
const { changeProp } = this.props;
const { modalIsOpen } = this.state;
return(
<Container>
<div className='header'>
<h1>My Contacts
<button className='addContactButton' onClick={this.toggleModal}>+</button>
</h1>
<hr />
</div>
<Modal isOpen={modalIsOpen}>
<form ref='addContact' >
<div className='addContactHeader'>
<button className='saveButton' onClick={changeProp}>Save</button>
<button className='cancelButton' onClick={this.toggleModal}>Cancel</button>
</div>
<div id="circle">Add Photo</div>
<div className="inputFields">
<div className='nameInputs'>
<input type='text' ref='first' placeholder='first name' />
<input type='text' ref='last' placeholder='last name' />
</div>
<div className='extraInputs' >
<input type='text' ref='phone' placeholder='phone' />
<input type='text' ref='email' placeholder='email' />
</div>
</div>
</form>
</Modal>
</Container>
)
}
}
The last thing you need to do is decide where you want the change of the state/prop to be fire. Hope this helps.
to handle the parent from child you need to bind this to the child
Parent Component
class Component extends React.Component {
constructor(props) {
super(props)
this.state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
this.addContact = this.addContact.bind(this);
}
render() {
...
return <AddContact addContact = {this.addContact} />
}
addContact(event) {
...
alert('one contact added');
...}
}
inside AddContact Component :
you can call this.props.addContact() to excute the parent function

i cant transfer data from react child to parent ang during click on child set value of input in parent

it is my first React App
i want create simple typeahead(autocomplete)
i want when i click on searched list of item, this item will show in value of my Parent input
now my click doesnt work, working only search by name
it is my parent
`
import React, { Component } from 'react';
import logo from './logo.svg';
import './Search.css';
import Sugg from './Sugg';
class Search extends Component {
constructor(props) {
super(props);
this.onSearch = this.onSearch.bind(this);
this.handleClickedItem = this.handleClickedItem.bind(this);
this.onClick = this.onClick.bind(this);
this.state = {
companies: [],
searchedList: [],
value: ''
}
}
componentDidMount() {
this.fetchApi();
console.log(this.state.companies);
}
fetchApi = ()=> {
const url = 'https://autocomplete.clearbit.com/v1/companies/suggest?query={companyName}';
fetch(url)
.then( (response) => {
let myData = response.json()
return myData;
})
.then((value) => {
let companies = value.map((company, i) => {
this.setState({
companies: [...this.state.companies, company]
})
})
console.log(this.state.companies);
});
}
onSearch(arr){
// this.setState({companies: arr});
};
handleInputChange = () => {
console.log(this.search.value);
let searched = [];
this.state.companies.map((company, i) => {
console.log(company.name);
console.log(company.domain);
const tempName = company.name.toLowerCase();
const tempDomain = company.domain.toLowerCase();
if(tempName.includes(this.search.value.toLowerCase()) || tempDomain.includes(this.search.value.toLowerCase())) {
searched.push(company);
}
})
console.log(searched);
this.setState({
searchedList: searched
})
if(this.search.value == '') {
this.setState({
searchedList: []
})
}
}
handleClickedItem(data) {
console.log(data);
}
onClick = e => {
console.log(e.target.value)
this.setState({ value: e.target.value});
};
render() {
return (
<div className="Search">
<header className="Search-header">
<img src={logo} className="Search-logo" alt="logo" />
<h1 className="Search-title">Welcome to React</h1>
</header>
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Sugg searchedList={this.state.searchedList} onClick={this.onClick.bind(this)} />
</form>
</div>
);
}
}
export default Search;
`
and here my child component
i dont know how call correctly click event
import React from 'react';
const Sugg = (props) => {
console.log(props);
const options = props.searchedList.map((company, i) => (
<div key={i} >
<p onClick={() => this.props.onClick(this.props)}>{company.name}</p>
</div>
))
console.log(options);
return <div >{options}</div>
}
export default Sugg;
please help me who knows how it works
thanks a lot
In the parent you could modify your code:
onClick = company => {
console.log('company', company);
this.setState({ value: company.name});
};
and you don't need to bind this because onClick is an arrow function
<Sugg searchedList={this.state.searchedList} onClick={this.onClick} />
and in the child component, you need to use props from the parameters, not from the this context:
<p onClick={() =>props.onClick(company)}>{company.name}</p>

Categories

Resources