I believe I have my props setup correctly, but I keep getting "Cannot read property 'props' of undefined"
Child component:
const SearchResults = props => (
<div>
<div className="row" ><h4 style={{margin:"auto", marginBottom:"15px"}}>Search Results:</h4></div>
<table className="table table-striped">
<thead>
<tr>
{props.labels.map(label => ( <th key={label.Id}>{label.DisplayName}</th>))}
</tr>
</thead>
<tbody>
{ props.contracts.map((contract, i) => <tr key={i} data-id={contract.Id} onClick={() => this.props.handleContract(contract.Fields.filter(field => field.DataField==="IDXT001").map(field => field.DataValue))} className="clickable-row">{contract.Fields.map( docs => <td key={docs.Id}><span id={docs.DataField}>{docs.DataValue}</span></td>)}</tr> )}
</tbody>
</table>
</div>
)
Parent:
class SearchPage extends React.Component {
constructor(props) {
super(props);
this.state = {
labels: [],
contracts: [],
formValues:"",
pdfs:[],
id:"",
};
}
<SearchResults
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
handleContract={this.onClick}
/>
You need to change this.props.handleContract to props.handleContract. this doesn't exist in your functional component.
const SearchResults = props => (
<div>
<div className="row" ><h4 style={{ margin: "auto", marginBottom: "15px" }}>Search Results:</h4></div>
<table className="table table-striped">
<thead>
<tr>
{props.labels.map(label => (<th key={label.Id}>{label.DisplayName}</th>))}
</tr>
</thead>
<tbody>
{props.contracts.map((contract, i) => <tr key={i} data-id={contract.Id} onClick={() => props.handleContract(contract.Fields.filter(field => field.DataField === "IDXT001").map(field => field.DataValue))} className="clickable-row">{contract.Fields.map(docs => <td key={docs.Id}><span id={docs.DataField}>{docs.DataValue}</span></td>)}</tr>)}
</tbody>
</table>
</div>
);
On your parent, make sure you have bound the onClick function as mentioned in the comments.
class SearchPage extends React.Component {
constructor(props) {
super(props);
this.state = {
labels: [],
contracts: [],
formValues: "",
pdfs: [],
id: ""
};
}
onClick = () => {
// Bind the function like this.
}
render() {
return (
<SearchResults
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
handleContract={this.onClick}
/>
);
}
}
Related
Class component - list of items with a boolean property ; I've added onChange method to change state of this propery in a collection. When I try to compile I have:
Line 15:59: Array.prototype.map() expects a return value from arrow
function array-callback-return
import React from "react";
class ItemList extends React.Component {
constructor(props) {
super(props);
this.state = {
items: props.items
}
}
toggleCompleted = (position) => {
const updatedItems = this.state.items.map((item, idx) => {
position === idx ? {...item, completed: !item.completed} : item //err
})
this.setState({
items: updatedItems
})
}
render() {
return(
<div className="col-12 col-lg-8 mx-auto">
<h3 className="h3">Tasks</h3>
{this.state.items.length > 0 &&
<table className="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Description</th>
<th scope="col">Completed</th>
</tr>
</thead>
<tbody>
{this.state.items.map((item, idx) => {
return (
<tr key={idx+1}>
<th scope="row">{idx+1}</th>
<td>{item.title}</td>
<td>{item.description}</td>
<td>
<input
id={"completed".concat(idx)}
className="form-check-input"
type="checkbox"
checked={item.completed}
onChange={() => {this.toggleCompleted(idx)}}/>
</td>
</tr>
);
})}
</tbody>
</table>
}
</div>
)
}
}
export default ItemList;
Why?
Add missing return statement:
const updatedItems = this.state.items.map((item, idx) => {
return position === idx ? {...item, completed: !item.completed} : item
})
or remove {}
const updatedItems = this.state.items.map((item, idx) =>
position === idx ? {...item, completed: !item.completed} : item
)
Read more about basics here
Add a "return" before
position === idx ? {...item, completed: !item.completed} : item
I want to create update operation on ReactJS
first I set edit button as
export default class Viewcustomer extends React.Component{
constructor(props) {
super(props)
this.state = {
customers:[]
}
}
componentDidMount() { /* lifecycle method*/
axios.get(`http://localhost:5001/customers/customerView`)
.then(res => {
const customers = res.data;
this.setState({customers});
})
}
onChange = (e) => {
this.setState(
{[e.target.name]: e.target.value}
)
}
edit=personId=>{
console.log(personId);
}
render(){
return(
<div>
<br/><br/>
<div className='container' style={container}>
<h1 style={h1}>Customer Details</h1>
<div className='col-md-12' style={colmd12}>
<br/><br/>
<div className="tbl-header" style={tblheader}>
<table className="table" style ={table} >
<thead className='thead' >
<tr className='tr' >
<th >Id</th>
<th>name</th>
<th>NIC</th>
<th>type</th>
<th>Delete</th>
<th>Update</th>
</tr>
</thead>
</table>
</div>
<div className="tbl-content" style={tblcontent}>
<table className="table" style ={table} >
<tbody>
{ this.state.customers.map(person =>
<tr className='td' style={td}>
<td>{person.Id}</td>
<td>{person.name}</td>
<td>{person.NIC}</td>
<td>{person.type}</td>
<td><Link to="update"><i class="fa fa-trash-o" style={iconstyle}></i></Link></td>
<td><Link to="update"><i class="fa fa-file" style={iconstyle} onClick={()=>this.state.edit(person.Id)}></i></Link></td>
</tr>)}
</tbody>
</table>
</div>
</div>
</div>
</div>
)
}
}
the update icon routes to Updatecustomer.jsx file.
then I set the edit fuction on Update.jsx file
import React from "react";
export default class Updatecustomer extends React.Component{
constructor(props){
super(props)
this.state={
update:[]
}
}
onChange = (e) => {
this.setState(
{[e.target.name]: e.target.value}
)
}
edit=personId=>{
console.log(personId);
}
render(){
return(
<div>
</div>
)
}
}
then my browser gives the following error: (TypeError: this.state.edit is not a function)
It is very big help if you have some ideas to fix this.
The edit function is not part of your state. Use onClick={()=>this.edit(person.Id)} instead.
Just remove state part and try
this.edit(person.id)
I have data that I need to show in table, for all rows I would like to use collapse function. Now I have working code that is collapsing all rows on click, but in what way I can collapse only one already clicked?
This is my code:
class Data extends React.Component {
constructor(props) {
super(props);
this.state = {
datas: [
{name: "or1", status: 11},
{name: "or3", status: 2},
{name: "or2", status: 22},
],
expanded: [],
isOpen: true,
};
}
toogleContent(openIs) {
this.setState({
isOpen: !openIs
})
}
render() {
return (
<Table responsive>
<thead className="text-primary">
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{this.state.datas.map((data, i) => (
<tr id={i} onClick={this.toogleContent.bind(this, this.state.isOpen)}>
<td>{data.name}</td>
<td><Collapse isOpen={this.state.isOpen}>
{data.status}</Collapse>
</td>
</tr>
))}
</tbody>
</Table>
)
}
}
I used their indexes to find out if they are opened or not, but you can use their names too, or add at data object a key isOpened =>
state={
isOpenIndexes = []
}
toogleContent(index) {
// we check if already opened
this.state.isOpenIndexes.find(openedIndex => openedIndex ===index ) ?
this.setState({
isOpenIndexes: this.state.isOpenIndexes.filter(openedIndex => openedIndex!==index)
})
:
this.setState({
isOpenIndexes: isOpenIndexes.concat([index])
})
}
{datas.map((data, i) => (
<tr id={i} onClick={this.toogleContent.bind(this, i)} isOpened={this.state.isOpenIndexes.find(openedIndex => openedIndex ===i )}>
<td>{data.name}</td>
<td>{data.status}</td>
</tr>
))}
When I click the "pending" button, the status does not change with this code, and shows the message
TypeError: this.state.data.map is not a function
Please help me!
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "farid",
age: 15,
status: "pending"
},
{
id: 2,
name: "kamal",
age: 15,
status: "pending"
}
],
}
}
movementappTDClick = (id) => () => {
const index = this.state.data.findIndex((data) => {
return data.id === id
})
let data = Object.assign({}, this.state.data[index]);
console.log('data is', data);
data.status = "approved"
console.log("sec data is", data);
this.setState({ data });
};
render() {
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{this.state.data && this.state.data.map(movement => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button
onClick={this.movementappTDClick(movement.id)}
>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}
try to modify your movementappTDClick function.
movementappTDClick = index => {
const data = [...this.state.data];
const row = data[index];
row.status = "approved";
data.splice(index, 1, row);
this.setState({ data });
};
render() {
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{this.state.data &&
this.state.data.map((movement, index) => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button onClick={() => this.movementappTDClick(index)}>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}
I modified your code. Please check this.
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "farid",
age: 15,
status: "pending"
},
{
id: 2,
name: "kamal",
age: 15,
status: "pending"
}
],
}
}
movementappTDClick = (index) => () => {
const { data } = this.state;
data[index] = {
...data[index],
status: 'approved'
}
this.setState({ data }); };
render() {
const { data } = this.state;
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{data && _.map((data || []), (movement, index) => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button
onClick={this.movementappTDClick(index)}
>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}
openBookDetails sets isBookDetailsOpen: true which should change the className in showHideClassName to modal display-block and it should show on the screen but the modal doesn't show. However it appears in Elements in the Development tools
import React, { Component } from 'react';
import './Update.css';
import Search from '../Search/Search';
// import Modal from './Modal/Modal';
const Table = ({ data, openBookDetails }) => (
<table class="table table-hover">
<thead>
<tr class="table-primary">
<th scope="col">Title</th>
<th scope="col">Author</th>
<th scope="col">ISBN</th>
<th scope="col">No. Of Copies</th>
</tr>
</thead>
<tbody>
{data.map(row =>
<TableRow key={row.id} row={row} openBookDetails={openBookDetails}/>
)}
</tbody>
</table>
)
const TableRow = ({ row, openBookDetails }) => (
<tr class="table-light" onClick={openBookDetails}>
<th scope="row" >{row.title}</th>
<td >{row.author}</td>
<td >{row.isbn}</td>
<td >24</td>
</tr>
)
const Modal = ({ closeBookDetails, isBookDetailsOpen, children }) => {
const showHideClassName = isBookDetailsOpen ? 'modal display-block' : 'modal display-none';
return (
<div className={showHideClassName}>
<section className='modal-main'>
{children}
<button
onClick={closeBookDetails}
>
Close
</button>
</section>
</div>
);
};
class Update extends Component{
constructor(props) {
super(props);
this.state = {
value: '',
suggestions: [],
setOfAllBooks: [],
searchedBooks: [],
isBookDetailsOpen: false,
};
this.openBookDetails = this.openBookDetails.bind(this);
this.setTableData = this.setTableData.bind(this);
}
setTableData(searchedBook){
this.setState({searchedBooks: searchedBook})
console.log(this.state.searchedBooks)
}
openBookDetails(){
console.log('openBookDetails')
this.setState({ isBookDetailsOpen: true})
}
closeBookDetails(){
this.setState({ isBookDetailsOpen: false})
}
render(){
return(
<main>
<div class="container">
<Search state={this.state} setTableData={this.setTableData} />
<Table data={this.state.searchedBooks} openBookDetails={this.openBookDetails}/>
<Modal isBookDetailsOpen={this.state.isBookDetailsOpen} closeBookDetails={this.closeBookDetails} />
{/* <Modal /> */}
</div>
</main>
)
}
}
export default Update;