Applying className/onClick/onChange not working on Custom React Component
I'm almost new to react
.
I'm trying to create a simple editing and creating mask.
Here is the code:
import React, { Component } from 'react';
import Company from './Company';
class CompanyList extends Component {
constructor(props) {
super(props);
this.state = {
search: '',
companies: props.companies
};
}
updateSearch(event) {
this.setState({ search: event.target.value.substr(0,20) })
}
addCompany(event) {
event.preventDefault();
let nummer = this.refs.nummer.value;
let bezeichnung = this.refs.bezeichnung.value;
let id = Math.floor((Math.random()*100) + 1);
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "../data/post/json/companies",
data: ({
_token : window.Laravel.csrfToken,
nummer: nummer,
bezeichnung : bezeichnung,
}),
success: function (data) {
id = data.Nummer;
this.setState({
companies: this.state.companies.concat({id, nummer, bezeichnung})
})
this.refs.bezeichnung.value = '';
this.refs.nummer.value = '';
}
});
}
editCompany(event) {
alert('clicked');
event.preventDefault();
this.refs.bezeichnung.value = company.Bezeichnung;
this.refs.nummer.value = company.Nummer;
}
render() {
let filteredCompanies = this.state.companies.filter(
(company) => {
return company.bezeichnung.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
return (
<div>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Suche</div>
<div className="col-xs-12 col-sm-12 col-md-9 col-lg-9">
<div className="form-group">
<input className="form-control" type="text" value={this.state.search} placeholder="Search" onChange={this.updateSearch.bind(this)} />
</div>
</div>
</div>
<form onSubmit={this.addCompany.bind(this)}>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Neuen Eintrag erfassen</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="nummer" placeholder="Nummer" required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="bezeichnung" placeholder="Firmenname" required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<button type="submit" className="btn btn-default">Add new company</button>
</div>
</div>
</div>
</form>
<div className="row">
<div className="col-xs-10 col-sm-10 col-md-10 col-lg-10">
<ul>
{
filteredCompanies.map((company)=> {
return <Company company={company} key={company.id} onClick={this.editCompany.bind(this)} />
})
}
</ul>
</div>
</div>
</div>
);
}
}
export default CompanyList
The Company class looks like this:
import React, { Component } from 'react';
const Company = ({company}) =>
<li>
{company.Nummer} {company.Bezeichnung}
</li>
export default Company
My question now is, why is the onclick
event not being fired, when I click on a Company
.
In this part:
<ul>
{
filteredCompanies.map((company)=> {
return <Company company={company} key={company.id} onClick={this.editCompany.bind(this)} className="Company"/>
})
}
</ul>
Solution 1:
The reason is pretty simple, when you onClick like
<Company company={company} key={company.id} onClick={this.editCompany.bind(this)} />
its not an event that is set on the component, rather a prop that is being passed to the Company
component and can be accessed like props.company
in the Company component,
what you need to do is to specify the onClick
event and className
in the Company component like
import React, { Component } from 'react';
const Company = ({company, onClick, className}) => (
<li onClick={onClick} className={className}>
{company.Nummer} {company.Bezeichnung}
</li>
)
export default Company
The function passed on as prop to the Company
component can be passed on by any name like
<Company company={company} key={company.id} editCompany={this.editCompany.bind(this)} className="Company"/>
and used like
import React, { Component } from 'react';
const Company = ({company, editCompany}) => (
<li onClick={editCompany}>
{company.Nummer} {company.Bezeichnung}
</li>
)
Solution 2:
you have to bind the event on you child component :
import React, { Component } from 'react';
const Company = ({ company, onClick }) =>
<li onClick={onClick}>
{company.Nummer} {company.Bezeichnung}
</li>
export default Company
or
const Company = ({ company, ...props }) =>
<li {...props}>
{company.Nummer} {company.Bezeichnung}
</li>
if you want that all props passed to your Compagny component (exept compagny) goes to your li tag. see ES6 spread operator and rest.