How to delete an item from a table in 'React' using 'Redux' - reactjs

Essentially the app at this point displays a list "Students" in the view saved to the data base—now I'd like to be able to delete a Student and have that persist as well. I believe the answer is in the component itself.
Here is what I have thus far—this is my Students component:
import React, { Component } from "react";
import store from "../store";
import { scrubStudent } from "../reducers";
export default class Students extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.deleteStudent = this.deleteStudent.bind(this);
}
deleteStudent(itemIndex) {
console.log(this.state);
var students = this.state.students;
store.dispatch(scrubStudent(this.state));
students.splice(itemIndex, 1);
this.setState({
students: students
});
}
render() {
var students = this.props.students;
return (
<div className="container">
<div className="sixteen columns">
<h1 className="remove-bottom">Students</h1>
<h5>List of current students and their campus</h5>
<hr />
</div>
<div className="sixteen columns">
<div className="example">
<div>
<table className="u-full-width">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Campus</th>
</tr>
</thead>
<tbody>
{students.map(function(student, index) {
return (
<tr key={index}>
<td>
{student.id}
</td>
<td>
{student.name}
</td>
<td>
{student.email}
</td>
<td>
{student.campus}
</td>
<td>
<a
className="button button-icon"
onClick={this.deleteStudent(index)}
>
<i className="fa fa-remove" />
</a>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
Right now I get index.js:90 TypeError: Cannot read property 'deleteStudent' of undefined
Thanks in advance!
UPDATE
Based on Matthew's suggestion I sought guidance (I am in school) from a teacher, he helped me wire the following:
But now I am getting the following error:
`index.js:90 TypeError: Cannot read property 'setState' of undefined`
I am going to dig into the reason for that!
import React, { Component } from "react";
import store from "../store";
import { deleteStudent } from "../reducers";
export default class Students extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.deleteStudent = this.deleteStudent.bind(this);
}
componentDidMount() {
this.unsubscribe = store.subscribe(function() {
this.setState(store.getState());
});
}
componentWillUnmount() {
this.unsubscribe();
}
deleteStudent(index) {
console.log(this.state);
var students = this.state.students;
store.dispatch(deleteStudent(index));
this.state = store.getState();
}
render() {
var students = this.props.students;
return (
<div className="container">
<div className="sixteen columns">
<h1 className="remove-bottom">Students</h1>
<h5>List of current students and their campus</h5>
<hr />
</div>
<div className="sixteen columns">
<div className="example">
<div>
<table className="u-full-width">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Campus</th>
</tr>
</thead>
<tbody>
{students.map(function(student, index) {
return (
<tr key={index}>
<td>
{student.id}
</td>
<td>
{student.name}
</td>
<td>
{student.email}
</td>
<td>
{student.campus}
</td>
<td>
<a
className="button button-icon"
onClick={() => this.deleteStudent(student.id)}
key={index}
>
<i className="fa fa-remove" />
</a>
</td>
</tr>
);
}, this)}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
This is my reducer:
import { combineReducers } from "redux";
import axios from "axios";
// INITIAL STATE
const initialState = {
students: [],
campuses: []
};
//ACTION CREATORS
const UPDATE_NAME = "UPDATE_NAME";
const ADD_STUDENT = "ADD_STUDENT";
const DELETE_STUDENT = "DELETE_STUDENT";
const GET_STUDENTS = "GET_STUDENTS";
const UPDATE_CAMPUS = "UPDATE_CAMPUS";
const GET_CAMPUS = "GET_CAMPUS";
const GET_CAMPUSES = "GET_CAMPUSES";
// ACTION CREATORS
export function updateName(name) {
const action = {
type: UPDATE_NAME,
name
};
return action;
}
export function addStudent(student) {
return {
type: ADD_STUDENT,
student
};
}
export function scrubStudent(student) {
return {
type: DELETE_STUDENT,
student
};
}
export function getStudents(students) {
const action = {
type: GET_STUDENTS,
students
};
return action;
}
export function updateCampus(campus) {
const action = {
type: UPDATE_CAMPUS,
campus
};
return action;
}
export function getCampus(campus) {
const action = {
type: GET_CAMPUS,
campus
};
return action;
}
export function getCampuses(campuses) {
const action = {
type: GET_CAMPUSES,
campuses
};
return action;
}
//THUNK CREATORS
export function fetchStudents() {
return function thunk(dispatch) {
return axios
.get("/api/students")
.then(function(res) {
return res.data;
})
.then(function(students) {
return dispatch(getStudents(students));
})
.catch(function(err) {
return console.error(err);
});
};
}
export function postStudent(student) {
return function thunk(dispatch) {
return axios
.post("/api/students", student)
.then(function(res) {
return res.data;
})
.then(function(newStudent) {
return dispatch(addStudent(newStudent));
})
.catch(function(err) {
return console.error(err);
});
};
}
export function deleteStudent(student) {
return function thunk(dispatch) {
return axios
.delete("/api/students/" + student.toString())
.then(function(res) {
return res.data;
})
.then(function(student) {
return dispatch(scrubStudent(student));
})
.catch(function(err) {
return console.error(err);
});
};
}
export function fetchCampuses() {
return function thunk(dispatch) {
return axios
.get("/api/campuses")
.then(function(res) {
return res.data;
})
.then(function(campuses) {
return dispatch(getCampuses(campuses));
})
.catch(function(err) {
return console.error(err);
});
};
}
export function postCampus(student) {
return function thunk(dispatch) {
return axios
.post("/api/campuses", campuse)
.then(function(res) {
return res.data;
})
.then(function(newCampus) {
return dispatch(getCampus(newCampus));
})
.catch(function(err) {
return console.error(err);
});
};
}
// REDUCER
const rootReducer = function(state = initialState, action) {
var newState = Object.assign({}, state);
switch (action.type) {
case GET_STUDENTS:
newState.students = state.students.concat(action.students);
return newState;
case ADD_STUDENT:
newState.students = state.students.concat([action.student]);
return newState;
case DELETE_STUDENT:
newState.students = state.students.concat([action.student]);
return newState;
case GET_CAMPUSES:
newState.campuses = state.campuses.concat(action.campuses);
return newState;
case GET_CAMPUS:
newState.campuses = state.campuses.concat([action.campus]);
return newState;
default:
return state;
}
};
export default rootReducer;

You should use arrow function in order to keep the relevant context in the map function:
{students.map((student, index) => {
This way when you use this inside the function - it's your current component.

Related

How to pass method to functional component in ReactJS

I'm trying to pass method ref to functional component but somehow it doesn't work
Here is the function:
import { FaTrashAlt } from 'react-icons/fa';
const ArticlesData = props => {
return(
props.products.map(product => {
return (
<tr>
<td>{product.name}</td>
<td>{product.description}</td>
<td>{product.price}$</td>
<td>
<span className="removeProduct--Container" onClick={props.click}>
<FaTrashAlt className="remove--Icon" />
</span>
</td>
</tr>
)
}).reverse()
)
}
export default ArticlesData;
Here is the request I'm trying to pass:
onRemove = (id) => {
fetch(`http://localhost:5000/products/:${id}/delete`, {
method: 'POST'
})
}
And here is how I pass:
<ArticlesData products={this.state.products} click={this.onRemove}/>
Update:
controller:
router.post('/:id/delete', (req, res) => {
try {
console.log(req.params.id)
productService.deleteOne(req.params.id)
res.status(200)
} catch (error) {
console.log(error)
}
})
service:
function deleteOne(id) {
return Product.deleteOne({_id: id});
}
You need to call the function with parameter id.
I'm assuming your product object has id attribute:
import { FaTrashAlt } from 'react-icons/fa';
const ArticlesData = props => {
return(
props.products.map(product => {
return (
<tr>
<td>{product.name}</td>
<td>{product.description}</td>
<td>{product.price}$</td>
<td>
<span className="removeProduct--Container" onClick={() => props.click(product.id)}>
<FaTrashAlt className="remove--Icon" />
</span>
</td>
</tr>
)
}).reverse()
)
}
export default ArticlesData;
Change ArticlesData component's code
from onClick={props.click}
to onClick={() => props.click(product.id)}
Full code:
import React from "react";
import ArticlesData from "./ArticlesData";
export default class SomeName extends React.Component {
onRemove = (id) => {
console.log(id);
fetch(`http://localhost:5000/products/:${id}/delete`, {
method: 'POST'
})
};
render() {
return (
<>
<ArticlesData click={this.onRemove} />
</>
);
}
}
import { FaTrashAlt } from 'react-icons/fa';
const ArticlesData = props => {
return(
props.products.map(product => {
return (
<tr>
<td>{product.name}</td>
<td>{product.description}</td>
<td>{product.price}$</td>
<td>
<span className="removeProduct--Container" onClick={() => props.click(product.id)}>
<FaTrashAlt className="remove--Icon" />
</span>
</td>
</tr>
)
}).reverse()
)
}
export default ArticlesData;
CodeSandbox Demo

react state is one state behind button clicks

I am writing a simple react page that renders 2 different html tables based off of which button is clicked on the screen. The issue I am having is that the table that is rendered for each button click is associated with the previous button click. (E.G. if I click button 1 one time then click button 2 the table associated with button 1 will be displayed.)
I am new to react so in order to get the tables to update I refactored my code to hold as much of the state as possible in the App.js class, I created the toggleState callback to associate the button clicks with state change of the parent, and I then pass that to DataProvider via the endpoint property. I realize this is probably where the state / UI disconnect is occurring, but I'm uncertain of the cause since I'm adhering to react principles to the best of my capability.
my class structure is as follows:
App
/ \
/ \
/ \
DataProvider ButtonToggle
|
Table
If it is relevant the table class is building the table based off of an API call, I will add the code for this, but it is not causing me problems so I do not believe it to be the source of the issue.
App.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import DataProvider from "./DataProvider";
import Table from "./Table";
import ButtonToggle from "./ButtonToggle";
class App extends Component {
constructor(props){
super(props);
this.state = {
input : 'employees',
endpoint : "api/employees/"
};
console.log("constructor app: " + this.state.input + "\n" + this.state.endpoint);
}
toggleState(input) {
if(input == "employees") {
this.setState({input : input, endpoint: "api/employees/"});
}
else {
this.setState({input : input, endpoint: "api/categories/"});
}
console.log("toggleState " + this.state.input + "\n" + this.state.endpoint);
}
render() {
return (
<div className="col-lg-12 grid-margin">
<div className="card">
<div className="card-title">
<div className="row align-items-center justify-content-center">
<div className="col-3"></div>
<div className="col-6">
<h1> Striped Table</h1>
</div>
<div className="col-3"></div>
</div>
<ButtonToggle toggleInput={ (input) => this.toggleState(input)}/>
</div>
<div className="card">
<div className="card-title"></div>
<div className="card-body">
<DataProvider endpoint={this.state.endpoint}
render={data => <Table data={data} />} />
</div>
</div>
</div>
</div>
);
}
}
export default App;
DataProvider.js
class DataProvider extends Component {
static propTypes = {
endpoint: PropTypes.string.isRequired,
render: PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.state = {
data: [],
loaded: false,
placeholder: "Loading..."
};
}
componentWillReceiveProps(props) {
console.log("dataprov: " + this.props.endpoint);
this.componentDidMount();
}
componentDidMount() {
fetch(this.props.endpoint)
.then(response => {
if (response.status !== 200) {
return this.setState({ placeholder: "Something went wrong" });
}
return response.json();
})
.then(data => this.setState({ data: data, loaded: true }));
}
render() {
const { data, loaded, placeholder } = this.state;
return loaded ? this.props.render(data) : <p>{placeholder}</p>;
}
}
export default DataProvider;
ButtonToggle.js
class ButtonToggle extends Component {
constructor (props) {
super(props);
}
render() {
return (
<div className="row align-items-center justify-content-center">
<div className="col-3 center-in-div">
<button type="button" className="btn btn-info btn-fw" onClick={this.props.toggleInput.bind(this, 'categories')}> Categories </button>
</div>
<div className="col-3 center-in-div">
<button type="button" className="btn btn-info btn-fw" onClick={this.props.toggleInput.bind(this, 'employees')}>
Employees
</button>
</div>
<div className="col-6"></div>
</div>
);
}
}
export default ButtonToggle;
Table.js : I don't think this is a problem, but I may stand corrected.
import React from "react";
import PropTypes from "prop-types";
import key from "weak-key";
const Table = ({ data }) =>
!data.length ? (
<p>Nothing to show. Records: {data.length} </p>
) : (
<div className="table-responsive">
<h2 className="subtitle">
Showing <strong>{data.length} items</strong>
</h2>
<table className="table table-hover">
<thead>
<tr>
{Object.entries(data[0]).map(el => <th key={key(el)}>{el[0]}</th>)}
</tr>
</thead>
<tbody>
{data.map(el => (
<tr key={el.id}>
{Object.entries(el).map(el => <td key={key(el)}>{el[1]}</td>)}
</tr>
))}
</tbody>
</table>
</div>
);
Table.propTypes = {
data: PropTypes.array.isRequired
};
export default Table;
Below is the minimum working code I could come up with. Your Button and Table components can be dumb components which will get data from parent component and will present it.
Your Parent or container component will have logic to set the properties for Button and Table component.
As Table and Button components are dumb you can go with functional components.
I have added the code for calling api (I have tried to mimic the api call) and getting data in same parent component, you can separate it out.
You can work on style and validations as per your needs.
Let me know if you need any further help.
class ParentComponent extends Component {
constructor() {
super();
this.state = {
name: "Category"
}
this.onBtnClick = this.onBtnClick.bind(this);
}
componentDidMount() {
this.getData(this.state.name)
}
getData(name) {
if (name === "Category") {
this.apiCall("/Category").then((data) => {
this.setState({ data: data })
})
} else {
this.apiCall("/Employee").then((data) => {
this.setState({ data: data })
})
}
}
apiCall(url) {
return new Promise((res, rej) => {
setTimeout(() => {
if (url === "/Employee") {
res([{ "Emp Name": "AAA", "Emp Age": "20" }, { "Emp Name": "BBB", "Emp Age": "40" }])
} else {
res([{ "Cat Id": "XXX", "Cat Name": "YYY" }, { "Cat Id": "MMM", "Cat Name": "NNN" }])
}
}, 1000)
});
}
onBtnClick(name) {
let newName = "Category"
if (name === newName) {
newName = "Employee"
}
this.setState({ name: newName, data: [] }, () => {
this.getData(newName);
})
}
render() {
return (<>
<ButtonComponent name={this.state.name} onBtnClick={this.onBtnClick}></ButtonComponent>
<TableComponent data={this.state.data} />
</>)
}
}
const ButtonComponent = ({ name, onBtnClick }) => {
return <Button onClick={() => { onBtnClick(name) }}>{name}</Button>
}
const TableComponent = ({ data }) => {
function getTable(data) {
return < table >
<thead>
<tr>
{getHeading(data)}
</tr>
</thead>
<tbody>
{getRows(data)}
</tbody>
</table >
}
function getHeading(data) {
return Object.entries(data[0]).map((key) => {
return <th key={key}>{key[0]}</th>
});
}
function getRows(data) {
return data.map((row, index) => {
return <tr key={"tr" + index}>
{Object.entries(data[0]).map((key, index) => {
console.log(row[key[0]]);
return <td key={"td" + index}>{row[key[0]]}</td>
})}
</tr>
})
}
return (
data && data.length > 0 ?
getTable(data)
: <div>Loading....</div>
)
}

action method not getting called

I am trying to get a simple react-redux app to work and I am running into a weird error that I can't figure out. I am trying to simply update my current user's status and handle the store and it doesnt work. changeUserStatus is not getting called
setCurrentUserFirstName - works setCurrentUserHandle - doesn't
export const changeUserStatus = (userid,status) => async (dispatch, getState, { getFirebase }) => {
const firebase = getFirebase()
const databaseRef = firebase.database().ref()
const statusRef = databaseRef.child("users").child(userid).child("user_status")
statusRef.set(status).then(() => {
dispatch({ type: 'CHANGE_USER_STATUS' });
});
}
//home.js file
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { firebaseConnect } from 'react-redux-firebase'
import { compose } from 'redux'
import { Redirect } from 'react-router-dom'
import {changeUserStatus} from '../../store/actions/userActions'
class Users extends Component {
handleAcceptClickEvent1 =(e) =>{
console.log("accepted");
const { userid, status } = this.props;
changeUserStatus(e.target.name,"accepted");
}
handleRejectClickEvent1 =(e) =>{
console.log("rejected");
const { userid, status } = this.props;
changeUserStatus(e.target.name,"rejected");
}
reject =(e) =>{
console.log("rejected");
const { userid, status } = this.props;
this.props.changeUserStatus(userid=e.target.name,status="rejected");
}
UserCard = ({user}) =>{
const status = user.user_status;
let acceptComponent;
let rejectComponent;
if (status == "pending"){
acceptComponent = <td><button type="button" class="btn btn-success green" name ={user.user_id} onClick={this.handleAcceptClickEvent1}>Accept</button></td>
rejectComponent = <td><button type="button" class="btn btn-danger red" name ={user.user_id} onClick={this.handleRejectClickEvent1}>Reject</button></td>
}
else if(status == "accepted"){
acceptComponent = <td>Accepted</td>
rejectComponent = <td></td>
}
else{
acceptComponent = <td></td>
rejectComponent = <td>Rejected</td>
}
return (
<tr>
<th scope="row">{user.user_id}</th>
<td>{user.company_name}</td>
<td>{user.email}</td>
{acceptComponent}
{rejectComponent}
</tr>
)
}
render() {
const { users, auth } = this.props;
if (!auth.uid) return <Redirect to='/login' />
console.log(users);
return (
<div className="dashboard container">
<div className="row">
<div className="project-list section">
<div>
<p>Users</p>
</div>
<table className="table table-striped table-bordered" style={{ width: "100%" }}>
<thead>
<tr>
<th scope="col">User Id</th>
<th scope="col">Company Name</th>
<th scope="col">Email</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{users && users.map(user => {
return <this.UserCard user={user.value} key={user.value.id} />
})}
</tbody>
</table>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
users: state.firebase.ordered.users,
auth: state.firebase.auth
}
}
const mapDispatchToProps = (dispatch) => {
return{
changeUserStatus: (userid,status) => dispatch(changeUserStatus(userid,status))
}
}
export default compose(
connect(mapStateToProps),
firebaseConnect({ users: 'users' })
)(Users);
put this and check
export default compose(
connect(mapStateToProps,mapDispatchToProps),
firebaseConnect({ users: 'users' })
)(Users);

Issue with leave animation using React-Flip-Move

I'm using this module for my twitch API app: https://github.com/joshwcomeau/react-flip-move/
and currently having an issue with the leave animation. The enter animation works perfectly, fine, but unforunately, when I click 'x' on one of the channels, the element (in my case a ) moves up and to the right. How do I make it fade out in its current position?
import React, { Component } from 'react';
import { connect } from 'react-redux';
import FlipMove from 'react-flip-move';
import { selectUser, fetchUser, removeUser } from '../actions/index';
class UsersList extends Component {
constructor(props) {
super(props);
this.state = {
show: 'all',
};
this.fetchInitialUsers(this.props.initialUsers);
}
fetchInitialUsers(users) {
users.map(this.props.fetchUser);
}
renderUser(user) {
const { channelData, streamData } = user;
return (
<tr
key={channelData.display_name}
onClick={() => this.props.selectUser(user)}
className='list-item'>
<td>
<img src={channelData.logo} className='user-logo' />
</td>
<td>
{channelData.display_name}
</td>
<td>
{streamData.stream ?
<span className='online'>Online</span> :
<span className='offline'>Offline</span>}
</td>
<span
className="glyphicon glyphicon-remove"
onClick={() => this.props.removeUser(user)}></span>
</tr>
)
}
showOnline() {
this.setState({
show: 'online'
});
}
showOffline() {
this.setState({
show: 'offline'
});
}
showAll() {
this.setState({
show: 'all'
});
}
render() {
return (
<div className='col-sm-4'>
<div className='text-center'>
<div className='btn-group btn-group-sm' role='group'>
<button
className='btn btn-default'
onClick={this.showAll.bind(this)}>
All
</button>
<button
className='btn btn-default'
onClick={this.showOnline.bind(this)}>
Online
</button>
<button
className='btn btn-default'
onClick={this.showOffline.bind(this)}>
Offline
</button>
</div>
</div>
<div className='container'>
<table className='table table-hover'>
<thead>
<tr>
<th>Logo</th>
<th>Channel</th>
<th>Status</th>
</tr>
</thead>
{/* <tbody> */}
<FlipMove
typeName='tbody' enterAnimation='fade'
leaveAnimation='fade'>
{this.props.users.filter(user => {
const { show } = this.state;
const { streamData } = user;
if (show == 'online') {
return streamData.stream;
}
else if (show == 'offline') {
return !streamData.stream;
}
else {
return user;
}
}).map(this.renderUser.bind(this))}
</FlipMove>
{/* </tbody> */}
</table>
</div>
</div>
)
}
}
function mapStateToProps({ users, initialUsers }) {
return { users, initialUsers };
}
export default connect(mapStateToProps, { selectUser, fetchUser, removeUser })(UsersList);
just add maintainContainerHeight="true" to the flipmove attributes

React - why is this component not rendering anything?

I am trying to render some child components in a parent component but nothing is rendering. I'm not getting any console errors but there is no render. I can't figure out why this may be happening. The application I am working on is built with React, using a flux architecture.
Here is my code:
Parent Component:
import React from 'react';
import TableWithDataHeader from './TableWithDataHeader.jsx';
import TableWithDataBody from './TableWithDataBody.jsx';
import TableWithDataRowForm from './TableWithDataRowForm.jsx';
import AppStore from '../../stores/AppStore';
export default class TableWithData extends React.Component {
state = {rows: [], isEditing: false};
componentDidMount() {
let json = AppStore.getCells();
let rows = this.state.rows;
for (let key in json) {
{rows[key] = json[key]};
}
this.setState({rows});
console.log(rows);
}
handleEdit = (row) => {
this.setState({isEditing: true});
};
editStop = (formKey) => {
this.setState({isEditing: false});
};
handleSubmit = () => {
console.log('hello');
};
render() {
let {rows, isEditing} = this.state;
console.log(rows);
return (
<div>
<div className="row">
<table className="table table-striped">
<thead>
<TableWithDataHeader />
</thead>
<tbody>
{rows.map(row => this.state.isEditing ?
<TableWithDataRowForm formKey={row.id} key={row.id} editStop={this.editStop(formKey)} handleSubmit={this.handleSubmit} /> :
<TableWithDataBody key={row.id} value={row.historycells.contents} handleEdit={this.handleEdit(row)} />
)}
</tbody>
</table>
</div>
</div>
);
}
}
RowForm:
import React from 'react';
export default class TableWithDataRowForm extends React.Component {
editStop = () => {
this.props.editStop();
};
handleSubmit = (e) => {
e.preventDefault();
this.props.handleSubmit();
};
render() {
return (
<tr>
<td></td>
<td>
<button className=""><i className="btn btn-default" onClick={this.editStop}></i>Cancel</button>
<button className="btn btn-success"><i className="fa fa-cloud" onClick={this.handleSubmit}></i>Save</button>
</td>
</tr>
);
}
}
Table Head:
import React from 'react';
import AppStore from '../../stores/AppStore';
export default class TableWithDataHeader extends React.Component {
addHeaders() {
let headerArray = AppStore.getTable().columns;
let headerList = headerArray.map((element, index) => {
return (
<th key={index} id={element.id} className="text-center">{element.name}</th>
);
});
return headerList;
}
render() {
return (
<tr>
{this.addHeaders()}
<th></th>
</tr>
);
}
}
Table Body:
import React from 'react';
export default class TableWithDataBody extends React.Component {
handleEdit() {
this.props.handleEdit();
}
render() {
return (
<tr>
{this.props.histroycells.map(cell => {
return <Cell key={cell.id} value={cell.contents} />
})}
<td>
<button className="btn btn-primary" onClick={this.handleEdit}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>
);
}
}
The table header renders fine but neither the body of the table or the edit form shows up at all!
Any help would be much appreciated, especially examples!
Thanks for you time!
Maybe this will help:
Inside your <TableWithDataBody>component, you try to access this.props.historycells, but this isn't passed as a prop.
You render your table rows with:
<TableWithDataBody
key={row.id}
value={row.historycells.contents}
handleEdit={this.handleEdit(row)} />
Maybe if you change render to:
<TableWithDataBody
key={row.id}
historycells={row.historycells} // changed this parameter
handleEdit={this.handleEdit(row)} />
UPDATE:
The line which loops over the props should still read:
{this.props.historycells.map(cell => {
PS: please also fix typo in histroycells.
You have a typo in your code. histroycells in TableWithDataBody should be historycells.

Resources