I have been working with code that uses table,
working code
export class BoardList extends Component {
static propTypes = {
boards: PropTypes.array.isRequired,
getBoards: PropTypes.func.isRequired,
deleteBoard: PropTypes.func.isRequired,
}
componentDidMount() {
this.props.getBoards();
}
render(){
this.props.boards.sort((boardA, boardB) => {return boardA.id - boardB.id })
const sortRow = this.props.boards.map(board => {
return (
<tr key={board.id}>
<td>{board.id}</td>
<td>{board.author}</td>
<td>{board.title}</td>
<td>{board.created}</td>
<td>{board.updated}</td>
<td>
<button className="btn btn-danger btn-sm" onClick={this.props.deleteBoard.bind(this, board.id)}>
Delete
</button>
</td>
</tr>
)
})
return (
<Fragment>
<table className="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Author</th>
<th>Title</th>
<th>Created</th>
<th>Updated</th>
<th />
</tr>
</thead>
<tbody>
{this.props.boards.length > 0 && (sortRow)}
</tbody>
</table>
</Fragment>
)
}
}
const mapStateToProps = state => ({
boards: state.boards.boards
})
export default connect(mapStateToProps, {getBoards, deleteBoard})(BoardList)
However, if I use different element, it does not work.
export class BoardList extends Component {
constructor(props){
super(props)
this.createCard = this.createCard.bind(this)
}
static propTypes = {
boards: PropTypes.array.isRequired,
getBoards: PropTypes.func.isRequired,
deleteBoard: PropTypes.func.isRequired,
}
componentDidMount() {
this.props.getBoards();
}
createCard(board) {
return (
<div key={board.id}>
<div className="card text-white bg-primary mb-3" style="max-width:20rem">
<div className="card-header">{board.author}</div>
<div className="card-body">
<h4 className="card-title">{board.title}</h4>
<p className="card-text">{board.body}</p>
<img src={board.image} style="max-width:100px"/>
</div>
</div>
</div>
)
}
render() {
this.props.boards.sort((boardA, boardB) => { return boardA.id - boardB.id });
const cardBoard = this.props.boards.map(this.createCard);
return (
<Fragment>
<h2>Boards</h2>
{this.props.boards.length > 0 && (cardBoard)}
</Fragment>
)
}
const mapStateToProps = state => ({
boards: state.boards.boards
})
export default connect(mapStateToProps, {getBoards, deleteBoard})(BoardList)
I get Uncaught (in promise) TypeError: Cannot read property 'data' of undefined. That data is from the my redux action.
export const getBoards = () => (dispatch, getState) => {
axios
.get("api/boards/", tokenConfig(getState))
.then(res => {
dispatch({
type: GET_BOARDS,
payload: res.data
})
})
.catch(err => dispatch(returnErrors(err.response.data, err.response.status)));
}
}
I think both methods map the props, so there shouldn't be any issue, but since I am new to React, I must be missing something here.
Related
I have this on the front end (react) right now.
import '../styles/TourPage.css';
import React, { Component } from 'react';
import axios from 'axios'
class TourPage extends Component {
constructor(props) {
super(props);
this.state = {
myData: []
}
}
componentDidMount() {
axios.get('/getResults')
.then( res => {
console.log("Res is: ", res.data)
this.setState({
myData: res.data
});
})
console.log("res.data", this.state.myData)
}
render() {
console.log("res.data", this.state.myData)
return (
<table id="customers">
<tr>
<th>siteLocation</th>
<th>Services</th>
<th>cnum</th>
</tr>
{this.state.myData.length > 0? this.state.myData.map((data, index) => (
<tr>
{/* <tr key={index}> */}
<td>{data.location}</td>
<td>{data.Services}</td>
<td>{data.cnum}</td>
<button onClick={this.click} disabled={this.state.isLoading}> Delete </button>
{/* {this.state.data} */}
{/* </tr> */}
</tr>
))
: "No Data Found"}
</table>
);
}
}
export default TourPage;
What I want to do, is on a button click, set data._id in the state, and then call Axios to post it to the Node.JS backend server, so I can update the database. Basically to delete the document. as you can see below, I tried with <a href> but that seems to be an HTML-specific thing. I also tried with the button, but I cannot figure it out. How can I do this?
I have refactored most of your code. You can pass id using an anonymous arrow function.
Do modify this to suit your needs.
import { render } from "react-dom";
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) => {
// You'll get the id here
// Delete by id code goes here
};
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>{location}</td>
<td>{Services}</td>
<td>{cnum}</td>
<button
onClick={() => this.deleteById(_id)}
disabled={isLoading}
>
Delete
</button>
</tr>
))
: "No Data Found"}
</table>
);
}
}
export default TourPage;
Can you try this ?
render() {
deleteDoc = (id) => {
await fetch('service_url', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: id} )
.then(async response => {
await response.json().then(data => {
console.log(data);
});
})
.catch(err => {
console.log(err)
})
}
return (
<table id="customers">
<tr>
<th>siteLocation</th>
<th>Services</th>
<th>cnum</th>
</tr>
{this.state.myData.length > 0 ? this.state.myData.map((data, index) => (
<tr>
<td>{data.location}</td>
<td>{data.Services}</td>
<td>{data.cnum}</td>
<button onClick={this.deleteDoc(data._id)} disabled={this.state.isLoading}> Delete </button>
</tr>
))
: "No Data Found"}
</table>
);
}
I am fetching data using axios and then map state to props with redux but I have a problem. If I dispatch the action in componentDidUpdate() the action execute indefinitely and if I used the constructor(props) I get undefined value for props so where I should fetch the data ?
import React, { Component } from 'react'
import {connect} from 'react-redux'
import { getUserPosts } from '../../actions'
class UserPosts extends Component {
//UNSAFE_componentWillMount() {
//}
constructor(props) {
super(props);
console.log(props);
}
componentDidUpdate() {
//this.props.dispatch(getUserPosts(this.props.user_reducer.login?.user._id));
}
showUserPosts = (user) => (
Array.isArray(user.userPosts) ?
user.userPosts.map((item, i) => (
<tr key={i}>
<td>{i}</td>
<td>author</td>
<td>date</td>
</tr>
))
: null
)
render() {
let user = this.props.user_reducer;
//console.log(user.userPosts);
return (
<div>
<div className="user_posts">
<h4>Your reviews:</h4>
<table>
<thead>
<tr>
<th>Name</th>
<th>Author</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{this.showUserPosts(user)}
</tbody>
</table>
</div>
</div>
)
}
}
function mapStateToProps(state) {
//console.log(state);
return {
user_reducer: state.user_reducer
}
}
export default connect(mapStateToProps)(UserPosts)
action:
export function getUserPosts(userId) {
const req = axios.get(`/api/user_posts?user=${userId}`)
.then(res => res.data);
return {
type: 'GET_USER_POSTS',
payload: req
}
}
componentDidMount() is the best placement for the call to fetch.
Here is an example implementation of the axios fetch from componentDidMount():
import React from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
class UserPosts extends React.Component {
constructor(props) {
super(props)
// Initiate state with an empty array of user posts
this.state = { userPosts: [] }
}
componentDidMount() {
axios.get('http://api-url-here')
.then((response) => {
// Set the userPosts when data is received.
// render method will show user posts when state changes
this.setState({userPosts: response.data})
})
}
showUserPosts = (user) => (
Array.isArray(user.userPosts) ?
user.userPosts.map((item, i) => (
<tr key={i}>
<td>{i}</td>
<td>author</td>
<td>date</td>
</tr>
))
: null
)
render() {
let user = this.state;
//console.log(user.userPosts);
return (
<div>
<div className="user_posts">
<h4>Your reviews:</h4>
<table>
<thead>
<tr>
<th>Name</th>
<th>Author</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{this.showUserPosts(user)}
</tbody>
</table>
</div>
</div>
)
}
}
ReactDOM.render(<UserPosts />, document.getElementById('root'))
I am learning React js and this might sound like a newbie question. I am trying to implement a paginate function in react js from an API data. I am not sure how to implement the logic though. I have passed on props like the page size, current page and the data that needs to be rendered. Here is my code:
App.js
import React, { Component } from 'react'
import Result from './Result';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import Navbar from 'react-bootstrap/Navbar'
import Card from './Card';
import Loading from './Loading'
import Paginate from './Paginate';
export default class App extends Component {
constructor(){
super();
this.state = {
data: [],
totalData:[],
searchText:'',
searchResult:[],
isSearch:false,
isLoading:true,
pageSize:15,
currentPage:1
}
this.onSearchChange=this.onSearchChange.bind(this);
this.handlePageChange=this.handlePageChange.bind(this);
}
onSearchChange= (e) =>{
console.log("search change "+this.state.searchText)
this.setState({
searchText:e.target.value,
isSearch:true
})
console.log("api data"+this.state.data[0])
}
/* fetchSearchResult= () =>{
console.log(this.state.searchText)
console.log("inside fetch")
let store= this.state.data.map(item=>{
let {country}=item
return(country)
})
console.log(store)
var areEqual = store.includes(this.state.searchText);
console.log(this.state.areEqual)
return (areEqual)?
store:'not matched'
// return store;
} */
componentDidMount() {
const url =
'https://corona.lmao.ninja/countries?sort=country'
fetch(url)
.then(result => result.json())
.then(result => {
this.setState({
data: result.reverse(),
isLoading:false
})
})
const totalUrl =
'https://corona.lmao.ninja/all'
fetch(totalUrl)
.then(result => result.json())
.then(result => {
//let store=result;
//console.log("store data"+store)
this.setState({
totalData: result
})
console.log("2nd fetched data"+this.state.totalData)
})
}
handlePageChange= (page) =>{
this.setState({
currentPage:page
})
}
render() {
return (
this.state.isLoading?<Loading/>:
<div id="main">
<Navbar bg="dark" variant="dark">
<Navbar.Brand href="#home">
<Button id="live_text"
>Live</Button>
<img
alt=""
src="/logo.svg"
width="100"
height="30"
className="d-inline-block align-top"
/>{' '}
Covid-19 dashboard
{this.state.curTime}
</Navbar.Brand>
</Navbar>
<Form.Group>
<Form.Label>Search</Form.Label>
<Form.Control value={this.state.searchText}onChange={this.onSearchChange} type="text" placeholder="Enter country" />
</Form.Group>
<Card totalData={this.state.totalData}/>
<Paginate
dataCount={this.state.data.length}
pageSize={this.state.pageSize}
onPageChange={this.handlePageChange}
currentPage={this.state.currentPage}/>
<Result data={this.state.data}
toSearch={this.state.searchText}
searchCheck={this.state.isSearch}
searchValue={this.state.searchText}/>
</div>
)
}
}
Paginate.js
import React from 'react'
import _ from 'lodash'
export default function Paginate(props) {
const {pageSize, dataCount, onPageChange, currentPage}=props;
console.log("current page"+currentPage)
const pagesCount=Math.ceil(dataCount/pageSize);
const pages=_.range(1,pagesCount+1);
return (
<div>
<nav aria-label="...">
<ul class="pagination">
{pages.map((page)=>{
return(
<li key={page}class={(page===currentPage)?"page-item active":"page-item"}>
<a class="page-link" href="#" onClick={()=>onPageChange(page)}>{page}</a>
</li>
)
})}
</ul>
</nav>
</div>
)
}
Result.js
import React from 'react'
import Table from 'react-bootstrap/Table';
const Result = (props) => {
console.log('props value is:'+props.data)
let {searchCheck, searchValue}=props;
let update=props.data.map((item)=>{
const { countryInfo, country, cases, deaths, recovered, active, casesPerOneMillion} = item;
return(
(searchCheck)?country.toUpperCase().includes(searchValue.toUpperCase())?
<tbody>
<tr key={countryInfo._id}>
<td><img style={{height:'25px',width:'50px'}}src={countryInfo.flag}/></td>
<td>{country}</td>
<td>{cases}</td>
<td>{active}</td>
<td>{recovered}</td>
<th>{casesPerOneMillion}</th>
<td>{deaths}</td>
</tr>
</tbody>:
'':
<tbody>
<tr key={countryInfo._id}>
<td><img style={{height:'25px',width:'50px'}}src={countryInfo.flag}/></td>
<td>{country}</td>
<td>{cases}</td>
<td>{active}</td>
<td>{recovered}</td>
<th>{casesPerOneMillion}</th>
<td>{deaths}</td>
</tr>
</tbody>
)
})
return (
<div>
<Table striped bordered hover variant="dark">
<thead>
<tr>
<th>Flag</th>
<th>Country</th>
<th>Cases</th>
<th>Active</th>
<th>Recovered</th>
<th>Cases per one Million</th>
<th>Deaths</th>
</tr>
</thead>
{update}
</Table>
</div>
)
}
export default Result;
Codesandbox live
In my solution, I am fetching the required records from data based on page no and storing them in a new array( as a state) and passing them to Result.js
Tips: Use the key in Result.js at the top level of children in Result.js you are using the key at the tag instead of that you need to you it on
App.js
import React, { Component } from "react";
import Result from "./Result";
import Paginate from "./Paginate";
export default class App extends Component {
constructor() {
super();
this.state = {
data: [],
totalData: [],
searchText: "",
searchResult: [],
isSearch: false,
isLoading: true,
pageSize: 15,
currentPage: 1,
dataToShow: []
};
this.onSearchChange = this.onSearchChange.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
}
onSearchChange = e => {
this.setState({
searchText: e.target.value,
isSearch: e.target.value === "" ? false : true
});
};
/* fetchSearchResult= () =>{
console.log(this.state.searchText)
console.log("inside fetch")
let store= this.state.data.map(item=>{
let {country}=item
return(country)
})
console.log(store)
var areEqual = store.includes(this.state.searchText);
console.log(this.state.areEqual)
return (areEqual)?
store:'not matched'
// return store;
} */
componentDidMount() {
const url = "https://corona.lmao.ninja/countries?sort=country";
fetch(url)
.then(result => result.json())
.then(result => {
this.setState({
data: result.reverse(),
dataToShow: result.slice(0, 15),
isLoading: false
});
});
const totalUrl = "https://corona.lmao.ninja/all";
fetch(totalUrl)
.then(result => result.json())
.then(result => {
// let store=result;
// console.log("store data"+store)
this.setState({
totalData: result
});
});
}
handlePageChange = page => {
const { data, pageSize } = this.state;
this.setState({
currentPage: page,
dataToShow: data.slice(pageSize * (page - 1), pageSize * (page - 1) + 15)
});
};
render() {
const {
searchText,
data,
pageSize,
currentPage,
isSearch,
dataToShow
} = this.state;
return (
<div id="main">
<input
value={searchText}
onChange={this.onSearchChange}
type="text"
placeholder="Enter country"
/>
<Paginate
dataCount={data.length}
pageSize={pageSize}
onPageChange={this.handlePageChange}
currentPage={currentPage}
/>
<Result
data={isSearch ? data : dataToShow}
toSearch={searchText}
searchCheck={isSearch}
searchValue={searchText}
/>
</div>
);
}
}
Paginate.js
import React from "react";
export default function Paginate(props) {
const { pageSize, dataCount, onPageChange } = props;
const pagesCount = Math.ceil(dataCount / pageSize);
const Pages = new Array(pagesCount).fill(0);
// const Pages = [1,2,3,5]
return (
<div>
<nav aria-label="...">
{Pages.map((element, index) => (
<button
key={index}
type="button"
onClick={() => onPageChange(index + 1)}
>
{index + 1}
</button>
))}
</nav>
</div>
);
}
Result.js
import React from "react";
const Result = props => {
const { searchCheck, searchValue } = props;
const update = props.data.map(item => {
const {
countryInfo,
country,
cases,
deaths,
recovered,
active,
casesPerOneMillion
} = item;
return searchCheck ? (
country.toUpperCase().includes(searchValue.toUpperCase()) ? (
<tbody key={countryInfo._id}>
<tr>
<td>
<img
style={{ height: "25px", width: "50px" }}
src={countryInfo.flag}
/>
</td>
<td>{country}</td>
<td>{cases}</td>
<td>{active}</td>
<td>{recovered}</td>
<th>{casesPerOneMillion}</th>
<td>{deaths}</td>
</tr>
</tbody>
) : (
""
)
) : (
<tbody key={countryInfo._id}>
<tr>
<td>
<img
style={{ height: "25px", width: "50px" }}
src={countryInfo.flag}
/>
</td>
<td>{country}</td>
<td>{cases}</td>
<td>{active}</td>
<td>{recovered}</td>
<th>{casesPerOneMillion}</th>
<td>{deaths}</td>
</tr>
</tbody>
);
});
return (
<div>
<table>
<thead>
<tr>
<th>Flag</th>
<th>Country</th>
<th>Cases</th>
<th>Active</th>
<th>Recovered</th>
<th>Cases per one Million</th>
<th>Deaths</th>
</tr>
</thead>
{update}
</table>
</div>
);
};
export default Result;
I am failing to delete the clients from the API, i expected to click on Onclick button and the data should be deleted from the database:
Using the onclick button, the data should be deleted:
import React, { useRef } from 'react'
import ReactToPrint from 'react-to-print'
import { Table, Button } from 'react-bootstrap'
const Hello = () => {
alert('Name, Description, Start Date, End Date, Validity, Status')
}
class clientview extends React.Component {
constructor (props) {
super(props)
this.state = {
error: null,
clients: []
}
this.deleteTask = this.deleteTask.bind(this)
}
componentDidMount () {
const url = 'http://localhost:3001/clients/sel_all'
fetch(url)
.then(res => res.json())
.then(
result => {
console.log(result)
this.setState({
clients: result.data
})
},
error => {
this.setState({ error })
}
)
}
deleteTask (id, url = 'http://localhost:3001/clients/delete') {
return fetch(url + '/' + id, { method: 'DELETE' }).then(response =>
response.json()
)
}
render () {
const { error, clients, props } = this.state
if (error) {
return <div> Error:{error.message}</div>
} else {
return (
<div>
<h2>All Clients</h2>
<Table>
<thead>
<tr>
<th>No</th>
<th>Client Name</th>
<th>Client Address</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
{clients.map(client => (
<tr key={client.id}>
<td>{client.id}</td>
<td>{client.name}</td>
<td>{client.address}</td>
<td>{client.comment}</td>
<td>
<button onClick={Hello}>View Contract</button>
<button>
<ReactToPrint
trigger={() => <button>print</button>}
content={() => this.componentRef}
/>
</button>
<button
onClick={() => {
props.editRow(client)
}}
className='button'
>
Edit
</button>
</td>
<button
onClick={() => {
this.deleteTask.bind(this)
}}
>
Dele
</button>
</tr>
))}
</tbody>
</Table>
</div>
)
}
}
}
export default clientview
I did an input for an offline application form using React and built a view to display the form, but the view seems to keep giving error, i can't seem to identify it
Here is the code for the view:
import React from 'react'
export default class GradeData extends React.Component {
constructor (props) {
super(props)
this.state = {grades: []}
this.schoolDb = this.props.schoolDb
}
componentDidMount () {
this.updateGrades()
this.schoolDb.changes({
since: 'now',
live: true
}).on('change', (change) => {
this.updateGrades()
}).on('error', (err) => {
console.error(err)
})
}
updateGrades () {
this.schoolDb.allDocs({include_docs: true}).then((res) => {
var grades = res.rows.map((row) => row.grade)
this.setState({grades})
})
}
render () {
return (
<div className='eidsr-data'>
<div className='eidsr-data__header'>
<h3 className='eidsr-data__title'>Grades Overview</h3>
</div>
<div className='table-list'>
<table>
<thead>
<tr>
<th>Student ID</th>
<th>Semester</th>
<th>Period</th>
</tr>
</thead>
<tbody>
{this.state.grades.map((grade) => <DataRow key={grade._id} grade={grade} {...this.props} />)}
</tbody>
</table>
</div>
</div>
)
}
}
class DataRow extends React.Component {
render () {
let {grade} = this.props
return (
<tr >
<td>{grade.GradeInfo['studentID']}</td>
<td>{grade.GradeInfo['semester']}</td>
<td>{grade.GradeInfo['period']}</td>
</tr>
)
}
}
Here is the code for the form:
import React from 'react'
import GradeInfo from 'GradeInfo'
import {setUsers, getUsers, filterUsers} from 'UsersApi'
import UserList from 'UserList'
export default class GradeForm extends React.Component {
constructor (props) {
super(props)
this.state = {
grade: getUsers()
}
this.submitInfo = this.submitInfo.bind(this)
}
componentDidUpdate () {
setUsers(this.state.grade)
}
submitInfo (event) {
event.preventDefault()
let gradeInfo = Object.assign({}, this.props.grade)
this.setState({
grade: [
...this.state.grade,
{gradeInfo}
]
})
this.props.clearCurrentGrade()
}
render () {
let {
grade,
edit,
updateGrade,
updateGradeState,
} = this.props
return (
<div className='row'>
<div className='columns large-centered large-12 medium-12'>
<div className='form'>
<div className='container'>
<form action='' onSubmit={this.submitInfo}>
<div className='student-form__container'>
<GradeInfo edit={edit} handleChange={updateGrade('GradeInfo')} {...grade.GradeInfo} />
<button className='button expanded' type='submit'>Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
}