I'm having a problem with a modal which doesn't show up correctly. When I click the button the screen becomes all gray without showing me the content of the modal and when I try to insert a text in the input lets me do it, even if you don't see what you write.
Here's the code to understand the logic:
https://medium.com/#olinations/build-a-crud-template-using-react-bootstrap-express-postgres-9f84cc444438
And there's my App.js (List.js in that case) code :
import React, { Component } from "../../../node_modules/react";
import { Container, Row, Col } from "reactstrap";
import ModalForm from "../../Components/Modals/Modal";
import DataTable from "../../Components/Tables/DataTable";
import { CSVLink } from "react-csv";
class List extends Component {
state = {
items: []
};
getList = () => {
fetch("http://localhost:5000/api/azienda")
.then(res => res.json())
.then(items => this.setState({ items }))
.catch(err => console.log(err));
};
addItemToState = item => {
this.setState(prevState => ({
items: [...prevState.items, item]
}));
};
updateState = item => {
const itemIndex = this.state.items.findIndex(data => data.id_azienda === item.id);
const newArray = [
// destructure all items from beginning to the indexed item
...this.state.items.slice(0, itemIndex),
// add the updated item to the array
item,
// add the rest of the items to the array from the index after the replaced item
...this.state.items.slice(itemIndex + 1)
];
this.setState({ items: newArray });
};
deleteItemFromState = id => {
const updatedItems = this.state.items.filter(item => item.id_azienda !== id);
this.setState({ items: updatedItems });
// console.log(id)
};
componentDidMount() {
this.getList();
}
render() {
return (
<Container className="App">
<Row>
<Col>
<h1 style={{ margin: "20px 0" }}>CRUD Database</h1>
</Col>
</Row>
<Row>
<Col>
<DataTable
items={this.state.items}
updateState={this.updateState}
deleteItemFromState={this.deleteItemFromState}
/>
</Col>
</Row>
<Row>
<Col>
<CSVLink
filename={"db.csv"}
color="primary"
style={{ float: "left", marginRight: "10px" }}
className="btn btn-primary"
data={this.state.items}
>
Download CSV
</CSVLink>
<ModalForm
buttonLabel="Aggiungi"
addItemToState={this.addItemToState}
/>
</Col>
</Row>
</Container>
);
}
}
export default List;
DataTable.js :
import React, { Component } from 'react'
import { Table, Button } from 'reactstrap';
import ModalForm from '../Modals/Modal'
class DataTable extends Component {
deleteItem = id_azienda => {
let confirmDelete = window.confirm('Vuoi Eliminarlo Definitivamente?')
if(confirmDelete){
fetch('http://localhost:5000/api/azienda', {
method: 'delete',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id_azienda
})
})
.then(response => response.json())
.then(item => {
this.props.deleteItemFromState(id_azienda)
console.log(item)
})
.catch(err => console.log(err))
}
console.log(id_azienda)
}
render() {
const items = this.props.items.map(item => {
return (
<tr key={item.id_azienda}>
<th scope="row">{item.id_azienda}</th>
<td>{item.nome_azienda}</td>
<td>{item.tipo}</td>
<td>
<div style={{width:"110px"}}>
<ModalForm buttonLabel="Modifica" item={item} updateState={this.props.updateState}/>
{' '}
<Button color="danger" onClick={() => this.deleteItem(item.id_azienda)}>Elimina</Button>
</div>
</td>
</tr>
)
})
return (
<Table responsive hover>
<thead>
<tr>
<th>ID</th>
<th>Nome Azienda</th>
<th>Tipo Azienda</th>
</tr>
</thead>
<tbody>
{items}
</tbody>
</Table>
)
}
}
export default DataTable;
Modal.js :
import React, { Component } from 'react'
import { Button, Modal, ModalHeader, ModalBody } from 'reactstrap'
import AddEditForm from '../Forms/AddEditForm'
class ModalForm extends Component {
constructor(props) {
super(props)
this.state = {
modal: false
}
}
toggle = () => {
this.setState(prevState => ({
modal: !prevState.modal
}))
}
render() {
const closeBtn = <button className="close" onClick={this.toggle}>×</button>
const label = this.props.buttonLabel
let button = ''
let title = ''
if(label === 'Modifica'){
button = <Button
color="warning"
onClick={this.toggle}
style={{float: "left", marginRight:"10px"}}>{label}
</Button>
title = 'Edit Item'
} else {
button = <Button
color="success"
onClick={this.toggle}
style={{float: "left", marginRight:"10px"}}>{label}
</Button>
title = 'Add New Item'
}
return (
<div>
{button}
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle} close={closeBtn}>{title}</ModalHeader>
<ModalBody>
<AddEditForm
addItemToState={this.props.addItemToState}
updateState={this.props.updateState}
toggle={this.toggle}
item={this.props.item} />
</ModalBody>
</Modal>
</div>
)
}
}
export default ModalForm;
and my AddEditForm.js :
import React,{Component} from 'react';
import { Button, Form, FormGroup, Label, Input,ModalFooter } from 'reactstrap';
class AddEditForm extends Component {
state = {
id_azienda: 0,
nome_azienda: '',
tipo: ''
}
onChange = e => {
this.setState({[e.target.name]: e.target.value})
}
submitFormAdd = e => {
e.preventDefault()
fetch('http://localhost:5000/api/azienda', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
nome_azienda: this.state.nome_azienda,
tipo: this.state.tipo
})
})
.then(response => response.json())
.then(item => {
if(Array.isArray(item)) {
this.props.addItemToState(item[0])
this.props.toggle()
} else {
console.log('failure Add data')
}
})
.catch(err => console.log(err))
}
submitFormEdit = e => {
e.preventDefault()
fetch('http://localhost:5000/api/azienda', {
method: 'put',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id_azienda: this.state.id_azienda,
nome_azienda: this.state.nome_azienda,
tipo: this.state.tipo
})
})
.then(response => response.json())
.then(item => {
if(Array.isArray(item)) {
// console.log(item[0])
this.props.updateState(item[0])
this.props.toggle()
} else {
console.log('failure edit data')
}
})
.catch(err => console.log(err))
}
componentDidMount(){
// if item exists, populate the state with proper data
if(this.props.item){
const { id_azienda, nome_azienda, tipo } = this.props.item
this.setState({ id_azienda, nome_azienda, tipo })
}
}
render() {
return (
<Form onSubmit={this.props.item ? this.submitFormEdit : this.submitFormAdd}>
<FormGroup>
<Label for="nome_azienda">Nome Azienda</Label>
<Input type="text" name="nome_azienda" id="nome_azienda" onChange={this.onChange} value={this.state.nome_azienda === null ? '' : this.state.nome_azienda} />
</FormGroup>
<FormGroup>
<Label for="tipo">Tipo Azienda</Label>
<Input type="text" name="tipo" id="tipo" onChange={this.onChange} value={this.state.tipo === null ? '' : this.state.tipo} />
</FormGroup>
<ModalFooter>
<Button>Submit</Button>
</ModalFooter>
</Form>
);
}
}
export default AddEditForm
Your help is much appreciated
I solved this by adding fade={false} in the modal tag, it worked to have the modal displayed.
I added display:block line in css and problem resolved.
Related
I am working in a CRUD table, for that i have created 2 files, one that list the table and the other that edit each item of the list. I am using a modal for editing or creating.
The interaction with the api and database are working fine. But there are two issues that are going on.
After clicking in the Button Submit in the file CategoryForm, the modal doesn't close, it still open, don't know how to pass this function from the list to the form. And use it from there.
The table does not reload with the new row added with the data inserted.(the data is going correctly to the api and database). Also thinks that need to pass this from the list component to the form and call it from there.
Thanks in advance. I don't know if having two files with two components is the best solution, so i am open to suggestions.
This is the List File, called Categories.jsx
import React, { Component } from 'react'
import { Alert, Modal, Button } from "react-bootstrap";
import Datatable from '../../../globalcomponents/datatable/Datatable';
import CategoryForm from './CategoryForm';
import { FaPencilAlt,FaTrashAlt } from 'react-icons/fa';
const Api = require('../../api/CategoriesApi.js')
class Categories extends Component {
constructor(props) {
super(props)
this.state = {
categories: [],
isLoaded: false,
error: null,
isOpen: false,
id: null
}
}
openModal = (id) => {
this.setState( (prev) => {
const state = prev.state;
return { ...state, id: id, isOpen:true };
});
};
closeModal = () => this.setState({ isOpen: false });
componentDidMount() {
Api.getCategories()
.then(response => {
const [error, data] = response
if (error) {
this.setState({
isLoaded: true,
categories: [],
error: data
})
} else {
this.setState({
isLoaded: true,
categories: data
})
}
})
}
removeCategory = (id) => {
var categories = [...this.state.categories];
var index = categories.findIndex(function(item, i){return item.id === id})
categories.splice(index, 1);
this.setState({categories});
Api.deleteCategory(id)
}
render() {
const { error, isLoaded, categories } = this.state
if (error) {
return (
<Alert color="danger">
Error: {error}
</Alert>
)
} else if (!isLoaded) {
return (
<Alert color="primary">
Loading...
</Alert>
)
} else {
return (
<>
<Button
className="float-right"
variant="primary"
onClick={e => this.openModal()}
>
Adicionar
</Button>
<h4 className="mt-4 mb-4">Categorias de investimentos</h4>
<Datatable>
<table className="table table-striped my-4 w-100">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Url (Slug)</th>
<th></th>
</tr>
</thead>
<tbody>
{categories.map(category => (
<tr key={category.id}>
<td>{category.id}</td>
<td>{category.title}</td>
<td>{category.slug}</td>
<td>
<Button
className="btn btn-danger float-right"
onClick={(event) =>
this.removeCategory(category.id)
}
><FaTrashAlt /></Button>
<Button
className="btn btn-success float-right mr-2 "
onClick={() =>this.openModal(category.id)}
>
<FaPencilAlt />
</Button>
</td>
</tr>
))}
</tbody>
</table>
</Datatable>
<Modal show={this.state.isOpen} onHide={this.closeModal}>
<Modal.Header closeButton>
<Modal.Title>Adicionar / Editar</Modal.Title>
</Modal.Header>
<Modal.Body>
<CategoryForm id={this.state.id || null}/>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
)
}
}
}
export default Categories
and this is the form file:
import React, { Component } from 'react'
import { Redirect } from 'react-router'
import { Row, Col, Alert, Button, Form, FormGroup, Label, Input } from 'reactstrap'
const Api = require('../../api/CategoriesApi.js')
class CategoryForm extends Component {
constructor(props) {
super(props)
this.state = {
category: {
id: this.getCategoryId(props),
title: '',
slug: '',
},
redirect: null,
errors: [],
reload: false
}
this.setTitle = this.setTitle.bind(this)
this.setSlug = this.setSlug.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
getCategoryId(props) {
try {
return props.id
} catch (error) {
return null
}
}
setTitle(event) {
let newVal = event.target.value || ''
this.setFieldState('title', newVal)
}
setSlug(event) {
let newVal = event.target.value || ''
this.setFieldState('slug', newVal)
}
setFieldState(field, newVal) {
this.setState((prevState) => {
let newState = prevState
newState.category[field] = newVal
return newState
})
}
handleSubmit(event) {
event.preventDefault()
let category = {
title: this.state.category.title,
slug: this.state.category.slug,
}
Api.saveCategory(category, this.state.category.id)
.then(response => {
const [error, errors] = response
if (error) {
this.setState({
errors: errors
})
} else {
this.setState(
() => this.setState({reload: true})
)
}
})
}
componentDidMount() {
if (this.props.id ) {
Api.getCategory(this.props.id).then((response) => {
const [error, data] = response;
if (error) {
this.setState({
errors: data
});
} else {
this.setState({
category: data,
errors: []
});
}
});
}
}
render() {
const { redirect, category, errors } = this.state
if (redirect) {
return (
<Redirect to={redirect} />
)
} else {
return (
<>
<Row>
<Col>
{errors.length > 0 &&
<div>
{errors.map((error, index) =>
<Alert color="danger" key={index}>
{error}
</Alert>
)}
</div>
}
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label for="title">Title</Label>
<Input type="text" name="title" id="title" value={category.title} placeholder="Enter title" onChange={this.setTitle} />
</FormGroup>
<FormGroup>
<Label for="slug">Slug</Label>
<Input type="text" name="slug" id="slug" value={category.slug} placeholder="Enter slug" onChange={this.setSlug} />
</FormGroup>
<Button color="success">Submit</Button>
</Form>
</Col>
</Row>
</>
)
}
}
}
export default CategoryForm
In one place you have const [error, data] = response in other const [error, errors] = response, is it intentional?
You don't pass any cb for close modal or update data to <CategoryForm id={this.state.id || null}/>.
Categories.jsx component doesn't know when you update data on API.
Maybe something like
<CategoryForm id={this.state.id || null}
onSubmit={() => {
closeModal()
Api.getCategories()
.then(...
}}/>`
OK, i found the way! Add the function, that close modal and update the list in the Categories.jsx, the name was addCategory()
class Categories extends Component {
constructor(props) {
super(props)
this.state = {
categories: [],
isLoaded: false,
error: null,
isOpen: false,
id: null
}
this.addCategory = this.addCategory.bind(this);
}
addCategory(id, slug, title) {
this.setState(prevState => ({
categories: [{id, slug, title }, ...prevState.categories]
}));
this.closeModal()
}
<Modal show={this.state.isOpen} onHide={this.closeModal}>
<Modal.Header closeButton>
<Modal.Title>Adicionar / Editar</Modal.Title>
</Modal.Header>
<Modal.Body>
<CategoryForm
id={this.state.id || null}
addCategory={this.addCategory}
/>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
And in the CategoryForm, create the const for each field props it to the function created in the list, props.addCategory
handleSubmit(event) {
event.preventDefault()
let category = {
title: this.state.category.title,
slug: this.state.category.slug,
}
Api.saveCategory(category, this.state.category.id)
.then(response => {
const [error, errors] = response
if (error) {
this.setState({
errors: errors
})
} else {
this.setState(
)
}
})
const form = event.target;
const id = " "
const title = form.elements["title"].value;
const slug = form.elements["slug"].value;
this.props.addCategory( id, slug, title);
form.reset();
}
I have created a GET and POST for my customer class and now I want to close the AddCustomer form and refresh the table in Customer class.
I want to call closeCreateForm of AddCustomer in Customer class.
import React from 'react';
import { Button, Form, Modal } from 'semantic-ui-react';
export default class AddCustomer extends React.Component {
constructor(props) {
super(props);
this.state = {
showCreateForm:false,
formData:{
name: '',
address: ''
}
}
this.handleChangeName = this.handleChangeName.bind(this);
this.handleChangeAddress = this.handleChangeAddress.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeName(event) {
const value = event.target.value;
console.log(value);
this.setState({formData:{name:value, address:this.state.formData.address}});
//name: ""
//address: ""
console.log(this.state.formData);
}
handleChangeAddress(event) {
const value = event.target.value;
console.log(value);
this.setState({formData:{name:this.state.formData.name, address:value}});
//name: "ram" but now there is no address in formData
console.log(this.state.formData);
}
handleSubmit(event) {
event.preventDefault();
////address: "aaaaa" now there no name in formData
console.log(this.state.formData);
this.setState({formData:{
name:this.state.name, address:this.state.address
}});
this.props.onAddFormSubmit(this.state.formData);
}
//On cancel button click close Create user form
closeCreateForm = () => {
this.setState({ showCreateForm: false })
}
//Open Create new Customer form
openCreateCustomer = () => {
this.setState({ showCreateForm: true })
}
render() {
return (
<div>
<Modal closeOnTriggerMouseLeave={false} trigger={
<Button color='blue' onClick={this.openCreateCustomer}>
New Customer
</Button>
} open={this.state.showCreateForm}>
<Modal.Header>
Create customer
</Modal.Header>
<Modal.Content>
<Form onSubmit={this.handleSubmit}>
<Form.Field>
<label>Name</label>
<input type="text" placeholder ='Name' name = "name"
value = {this.state.name}
onChange = {this.handleChangeName}/>
</Form.Field>
<Form.Field>
<label>Address</label>
<input type="text" placeholder ='Address' name = "address"
value = {this.state.address}
onChange = {this.handleChangeAddress}/>
</Form.Field>
<br/>
<Button type='submit' floated='right' color='green'>Create</Button>
<Button floated='right' onClick={this.closeCreateForm} color='black'>Cancel</Button>
<br/>
</Form>
</Modal.Content>
</Modal>
</div>
)
}
}
In her customer class onAddFormSubmit get called and new record is submitted to database then I want to clothe this form and refresh the table tor new data.
import React from 'react';
import { Table, Button } from 'semantic-ui-react';
import AddCustomer from './AddCustomer';
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.onAddFormSubmit = this.onAddFormSubmit.bind(this);
this.state = {
error: null,
isLoaded: false,
formClose:false,
users: []
}
}
//fetch data
componentDidMount() {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers();
myHeader.append('Content-type', 'application/json');
myHeader.append('Accept', 'application/json');
myHeader.append('Origin','https://localhost:44387');
const options = {
method: 'GET',
myHeader
};
fetch(customerApi, options)
.then(res => res.json())
.then(
(result) => {
this.setState({
users: result,
isLoaded: true
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
//close form
closeForm = event => {
this.props.closeCreateForm();
}
async onAddFormSubmit(data) {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers({
'Accept':'application/json',
'Content-type':'application/json'
});
fetch(customerApi,{
method:'post',
headers:myHeader,
body:JSON.stringify(data)
})
.then(res => res.json())
.then(
(result) => {
console.log("Customer add result");
console.log(result);
this.setState({
})
},(error) => {
this.setState({ error });
}
)
}
onEditCustomer = customerId => {
console.log("Clicked"+customerId);
}
render() {
const { users } = this.state;
return (
<div>
<AddCustomer onAddFormSubmit = {this.onAddFormSubmit}/>
<Table celled textAlign='center'>
<Table.Header>
<Table.Row>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Address</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body >
{
users.map(user => (
<Table.Row key={user.customerId}>
<Table.Cell>{user.customerId}</Table.Cell>
<Table.Cell>{user.name}</Table.Cell>
<Table.Cell>{user.address}</Table.Cell>
<Table.Cell>
<Button color='blue' onClick = {()=>this.onEditCustomer(user.customerId)}>Edit</Button>
</Table.Cell>
<Table.Cell>
<Button color='red'>Delete</Button>
</Table.Cell>
</Table.Row>
))
}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='5'>
No of Pages
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
</div>
)
}
}
I am trying to add customer using API. When I run the code I am getting 415 error something like this
POST https://localhost:44387/api/Customers 415 Customer.js:71 in browser console.
Here is my code. I have two files one Customer and Second is AddCustomer which is form.
Customer JS
import React from 'react';
import { Table, Button } from 'semantic-ui-react';
import AddCustomer from './AddCustomer';
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
users: []
}
this.onAddFormSubmit = this.onAddFormSubmit.bind(this);
}
//fetch data
componentDidMount() {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers();
myHeader.append('Content-type', 'application/json');
myHeader.append('Accept', 'application/json');
myHeader.append('Origin','https://localhost:44387');
const options = {
method: 'GET',
myHeader
};
fetch(customerApi, options)
.then(res => res.json())
.then(
(result) => {
this.setState({
users: result,
isLoaded: true
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
onAddFormSubmit(data) {
const customerApi = 'https://localhost:44387/api/Customers';
const myHeader = new Headers();
const options = {
method: 'POST',
myHeader: {
'Accept': 'application/json, text/plain',
'Content-Type': 'application/json;charset=UTF-8'
},
body: {
"name":"Rahul",
"address":"102 Hobson Street"
}
};
fetch(customerApi, options)
.then(res => res.json())
.then(
(result) => {
this.setState({
user:result
})
},(error) => {
this.setState({ error });
}
)
}
render() {
const { users } = this.state;
return (
<div>
<AddCustomer onAddFormSubmit = {this.onAddFormSubmit}/>
<h3>hello{JSON.stringify(this.state.fields)}</h3>
<Table celled textAlign='center'>
<Table.Header>
<Table.Row>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Address</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
<Table.HeaderCell>Action</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body >
{
users.map(user => (
<Table.Row key={user.customerId}>
<Table.Cell>{user.customerId}</Table.Cell>
<Table.Cell>{user.name}</Table.Cell>
<Table.Cell>{user.address}.Address</Table.Cell>
<Table.Cell>
<Button color='yellow'>Edit</Button>
</Table.Cell>
<Table.Cell>
<Button color='red'>Delete</Button>
</Table.Cell>
</Table.Row>
))
}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='5'>
No of Pages
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
</div>
)
}
}
When I open add customer form and hit submit button it gives me error on fetch. What am I doing wrong?
AddCustomer JS
import React from 'react';
import { Button, Form, Modal } from 'semantic-ui-react';
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.initialState = {
name: '',
address: ''
};
this.state = this.initialState;
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const name = event.target.name;
const value = event.target.value;
this.setState({
[name]:value,
})
}
handleSubmit(event) {
event.preventDefault();
this.props.onAddFormSubmit(this.state);
this.setState(this.initialState);
}
//On cancel button click close Create user form
closeCreateForm = () => {
this.setState({ })
}
//Open Create new Customer form
openCreateCustomer = () => {
this.setState({ })
}
render() {
return (
<div>
<Modal closeOnTriggerMouseLeave={false} trigger={
<Button color='blue' onClick={this.openCreateCustomer}>
New Customer
</Button>
} open={this.state.showCreateForm}>
<Modal.Header>
Create customer
</Modal.Header>
<Modal.Content>
<Form onSubmit={this.handleSubmit}>
<Form.Field>
<label>Name</label>
<input type="text" placeholder ='Name' name = "name"
value = {this.state.name}
onChange = {this.handleChange}/>
</Form.Field>
<Form.Field>
<label>Address</label>
<input type="text" placeholder ='Address' name = "address"
value = {this.state.address}
onChange = {this.handleChange}/>
</Form.Field>
<br/>
<Button type='submit' floated='right' color='green'>Create</Button>
<Button floated='right' onClick={this.closeCreateForm} color='black'>Cancel</Button>
<br/>
</Form>
</Modal.Content>
</Modal>
</div>
)
}
}
I think server is expecting different content-type.
And i see you calling .setState({ user: result }).
But you are mapping users[] in state.
I think what you need to do is
fetch(apiUrl)
.then(res => this.setState({ users: result}))
.catch(err => this.setState({error : err}))
I know several topics exist about this subject but i don't find the "real" answer....
First of all, i work on React JS and i'm a beginner ;)
With the YouTube API, i mapped the items in the JSON object to display video thumbnails in cards. On desktop mode, when i click on thumbnail, it trigger a modal with the video.
But on mobile, i have 2 issues.....
I want, in the same time, replace (maybe replaceWith and data-video can be helpfull...) the thumbnail by the video who match with, and i want to trigger autoplay and fullscreen.....i don't know if the second part is possible....Despite my research, i still don't if i can get around this mobile block....
Thanks a lot for the answers and the advices :)
Here is my code below :
import React, { Component } from 'react'
import axios from 'axios';
import posed from 'react-pose';
import ReactPlayer from 'react-player';
import { Card, CardImg, Col, Row, CardTitle, Modal, ModalBody, ModalHeader, Pagination, PaginationItem, PaginationLink } from 'reactstrap';
import './videos.css'
const Box = posed.div({
hidden: { opacity: 0 },
visible: { opacity: 1 }
});
class Videos extends Component {
constructor () {
super();
this.state = {
isVisible : true,
videos: [],
resultsDatas: "",
nextPage: "",
previousPage: "",
videoId: "",
search: "",
playing: false,
modal : false,
clickedVideoId: "",
clickedVideoTitle: ""
}
}
componentDidMount() {
axios.get('https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&showinfo=0&iv_load_policy=3&part=snippet,id&order=date&maxResults=24')
.then((result) => {
this.setState({
videos: result.data.items,
resultsDatas: result.data,
nextPage: result.data.nextPageToken});
console.log(this.state.videos);
}
)
setTimeout(() => {this.setState({ isVisible: !this.state.isVisible });
}, 400);
}
nextPage = () => {
axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.nextPage}`)
.then((result) => {
this.setState({
nextPage: result.data.nextPageToken,
previousPage: result.data.prevPageToken,
videos: result.data.items,
resultsDatas: result.data
});
})
}
previousPage = () => {
axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.previousPage}`)
.then((result) => {
this.setState({
nextPage: result.data.nextPageToken,
previousPage: result.data.prevPageToken,
videos: result.data.items,
resultsDatas: result.data});
})
}
//For search function
inputChange = (event) => {
this.setState({search: event.target.value })
}
playPause = (index) => {
let element = document.getElementById(`play-pause${index}`);
if (element.requestFullscreen) {
this.setState({playing: !this.state.playing})
}
}
toggleModal = () => {
this.setState({
modal: !this.state.modal
});
}
onThumbnailClick = (index) => {
this.setState({
clickedVideoId: this.state.videos[index].snippet.resourceId.videoId,
clickedVideoTitle: this.state.videos[index].snippet.title
})
var windowWidth = window.innerWidth;
if(windowWidth > 768){
this.toggleModal()
}
}
render() {
let mapedVideos = this.state.videos.filter(
(item) => {
return item.snippet.title.toLowerCase().indexOf(this.state.search) !==-1;
}
);
return (
<div>
{/* <Row className="search-pages-bar pt-3 d-flex justify-content-center">
<Pagination>
<PaginationItem onClick={this.previousPage}>
<PaginationLink previous href="#"/>
</PaginationItem>
<PaginationItem onClick={this.nextPage}>
<PaginationLink next href="#"/>
</PaginationItem>
</Pagination>
</Row> */}
<Box pose={this.state.isVisible ? 'hidden' : 'visible'}>
<Row className="custom-videos-row mb-5">
{mapedVideos.map((item, index) => {
this.state.videos.map((item) => {
if(item.snippet.title.length > 38) {
return (item.snippet.title=`${item.snippet.title.slice(0,37)}... `);
}
})
return (
<Col className="custom-videos-col" lg="3" md="4" sm="6" key={index}>
<Card className="card-wrapper" onClick={() => {this.onThumbnailClick(index)}}>
<CardImg className="video-thumbnail" src={item.snippet.thumbnails.medium.url} alt="thumb"></CardImg>
<CardTitle className="video-card-title pl-2"><img className="play-picto" src={process.env.PUBLIC_URL + '/images/play_L.png'} alt="play-picto"/>{item.snippet.title}
</CardTitle>
</Card>
</Col>
);
})}
<Modal className="video-modal" role="dialog" isOpen={this.state.modal} toggle={this.toggleModal}>
<ModalHeader className="custom-modal-header" toggle={this.toggleModal}>
<img src={process.env.PUBLIC_URL + './images/logo.png'} alt="La Baule TV logo" className="LBTV-logo"></img>
<span className="ml-2">{this.state.clickedVideoTitle}</span></ModalHeader>
<ModalBody>
<ReactPlayer className="video-player"
url={`https://www.youtube.com/watch?v=${this.state.clickedVideoId}`}
playing= {true}
config={{
youtube: {
playerVars: {
modestbranding: 1,
controls: 1,
rel: 0
}
}}}
/>
</ModalBody>
</Modal>
</Row>
</Box>
</div>
)
}
}
export default Videos;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I'm using ReactJS and I'm trying to do a delete confirm popover and it works but when I click on "delete" doesn't work at all!
I'm using a button and inside I have an Icon and when click should popover its data-content, and it does! but the onClick inside doesn't work, maybe it's the way that I'm writing it? Have no idea what's going on
What I'm doing wrong?
Thank you, hope you can help me!
import React, { Component } from 'react';
import moment from 'moment';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faTrashAlt, faEdit, faTimes } from '#fortawesome/free-solid-svg-icons'
import NewTask from '../NewTask/NewTask';
import './Tasks.css';
class Tasks extends Component {
constructor(props) {
super(props);
this.state = {
projectId: props._id,
project: props.project,
tasks: []
};
}
componentDidMount() {
fetch(`/dashboard/project/${this.props.projectId}/tasks`)
.then(response => {
return response.json()
}).then(task => {
this.setState({
tasks: task.tasks
})
}).catch(error => console.error('Error:', error));
}
appendTask = task => {
let tasks = this.state.tasks;
tasks.push(task);
this.setState({tasks});
}
removeTask = taskId => {
let tasks = this.state.tasks;
let taskToDel = tasks.find(function(element){
if(element._id === taskId) {
return element;
}
});
if(taskToDel) {
// Find index of task to remove
const index = tasks.indexOf(taskToDel);
// If task index is found remove task from array
if(index != -1)
tasks.splice(index, 1);
this.setState({tasks});
}
}
deleteTaskOnDb = task => {
let data = {taskId: task._id};
fetch(`/dashboard/project/${this.props.projectId}/tasks/delete`, {
method: 'delete',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(response => {
//if(response.status === 200)
return response.json()
}).then(taskId => {
this.removeTask(taskId);
}).catch(error => console.error('Error:', error));
}
render() {
//POPOVER FUNCTION HERE
$(function () {
$('[data-toggle="popover"]').popover()
})
//POPOVER FUNCTION HERE
const fontawesomeiconStyle = {
fontSize: '1em',
color: '#bd822a',
textAlign: 'center'
}
const listStyle = {
display:'flex',
flexFlow: 'row wrap',
justifyContent: 'space-between'
}
const { tasks } = this.state;
return (
<div>
<ul className="task-list">
{tasks.map(task =>
<li key={task._id} style={listStyle}> <div>
{task.tasktitle}
<br/>
<p style={{fontSize: '10px', color: '#a2a2a2'}}>{moment(task.created).format('MMM DD YY, h:mm A')} </p>
</div>
<div>
<p style={{fontSize: '12px', color: '#a2a2a2'}}>{task.taskcomment}</p>
</div>
<div>
//BUTTON HERE
<button type="button" className="example-popover btn--delete button--tasks" data-html="true" data-container="body" data-toggle="popover" data-placement="right" data-content="Are you sure? <button type='button' className='btn--delete button--tasks' onClick='{() => this.deleteTaskOnDb(task)}'> Delete</button>">
<FontAwesomeIcon style={fontawesomeiconStyle} icon={faTimes} />
</button>
//BUTTON HERE
</div>
</li>
)}
</ul>
{this.props.project &&
this.props.project._id &&
<NewTask projectId={this.props.project._id} appendTask={this.appendTask}/>
}
</div>
);
}
}
export default Tasks;