ReactJS - popover onClick insde data-content doesn't work - reactjs

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;

Related

I am not able to change state and pass props

I have the stake component that is rendered 4 times in the parent class component. I am trying to pass valueNewStake as prop to its parent component and group all the inputs in one common array (see allStakes). For a reason I am not able to change the state and also the dom does not render the button next to the component. Can anyone explain me why it is happening as I am new in react. Thanks
import React, { Component } from 'react';
import Stake from './stake';
class FetchRandomBet extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
bet: null,
value: this.props.value,
allStakes: ['']
};
}
async componentDidMount() {
const url = "http://localhost:4000/";
const response = await fetch(url);
const data = await response.json();
this.setState({
loading: false,
bet: data.bets,
});
}
render() {
const { valueProp: value } = this.props;
const { bet, loading } = this.state;
if (loading) {
return <div>loading..</div>;
}
if (!bet) {
return <div>did not get data</div>;
}
return (
< div >
{
loading || !bet ? (
<div>loading..</div>
) : value === 0 ? (
<div className="bet-list">
<ol>
<p>NAME</p>
{
bet.map(post => (
<li key={post.id}>
{post.name}
</li>
))
}
</ol>
<ul>
<p>ODDS</p>
{
bet.map(post => (
<li key={post.id}>
{post.odds[4].oddsDecimal}
<div className="stake-margin">
<Stake
allStakes={this.props.valueNewStake}
onChange={() => { this.setState({ allStakes: [...this.props.valueNewStake] }) }}
>
<button>ok</button>
</Stake>
</div>
</li>
))
}
</ul>
</div>
import React, { useState } from 'react';
import CurrencyInput from 'react-currency-input-field';
function Stake() {
const [newStake, setStake] = useState(['']);
const changeStake = (e) => {
setStake(e.target.value)
}
return (
<>
<CurrencyInput
onChange={changeStake}
valueNewStake={newStake}
style={{
marginLeft: "40px",
width: "50px"
}}
placeholder="Stake"
decimalScale={2}
prefix="£"
/>
{newStake}
</>
);
}
export default Stake;
You're not passing your props to your Stake component
function Stake({ allStakes, onChange }) {
// do something with your props here
const [newStake, setStake] = useState(['']);
const changeStake = (e) => {
onChange()
setStake(e.target.value)
}
return (
<>
<CurrencyInput
onChange={changeStake}
valueNewStake={newStake}
style={{
marginLeft: "40px",
width: "50px"
}}
placeholder="Stake"
decimalScale={2}
prefix="£"
/>
{newStake}
</>
);
}

React API call in componentDidMount, and componentWillReceiveProps (order confusion)

I'm fairly new to React and Redux. I'm having this issue where the ratings sometimes don't show up when I refresh the page (please see screenshot). I think it's because sometimes the user from Redux comes into componentWillReceiveProps before loadTeamsData executes, but I don't know why that would make ratings not show up. (Also, I feel like my code is crap... Any critic is appreciated!)
Home.js
export class Home extends React.Component {
state = {
upVote: null,
downVote: null,
clickedTeam: "",
teams: teams
};
// When component mounted, add in thumbUp & thumbDown properties to each team
componentDidMount() {
const { user } = this.props.auth;
console.log("didmount");
this.loadTeamsData();
// Stores user voting info to state when coming from a different page
if (user) {
if (!(Object.entries(user).length === 0)) {
console.log("user", user, user.upVote, user.downVote);
this.setState({
upVote: user.upVote,
downVote: user.downVote
});
}
}
}
// Loads teams thumbUp, thumbDown data to state
loadTeamsData = () => {
axios.get("/api/teams/").then(res => {
console.log("data", res.data);
this.setState({
teams: this.state.teams.map(team => {
res.data.map(vote => {
if (vote.id === team.id) {
team.thumbUp = vote.thumbUp;
team.thumbDown = vote.thumbDown;
}
return vote;
});
return team;
})
});
});
};
// When props from Redux come in, set the state
UNSAFE_componentWillReceiveProps(nextProps) {
const { user } = nextProps.auth;
if (user !== this.props.auth.user && user) {
console.log("willreceiveprops", `\n`, this.props.auth.user, user);
this.setState({
upVote: user.upVote,
downVote: user.downVote
});
}
}
// Handle click on thumbs
onClickHandler = (id, e) => {
const { alert } = this.props;
const up = e.target.classList.contains("up");
if (this.props.auth.isAuthenticated) {
if (up && this.state.upVote === "") {
if (id === this.state.downVote) {
alert.error("You cannot up vote and down vote the same team!");
} else {
this.props.update_up(id);
this.setState(prevState => {
return {
teams: prevState.teams.map(team => {
if (id === team.id) {
team.thumbUp = team.thumbUp + 1;
team.votedUpColor = { color: "#1E95E0" };
}
return team;
}),
clickedTeam: id,
upVote: id
};
});
alert.show(`You Up Voted ${id}`);
}
} else if (!up && this.state.downVote === "") {
if (id === this.state.upVote) {
alert.error("You cannot up vote and down vote the same team!");
} else {
this.props.update_down(id);
this.setState(prevState => {
return {
teams: prevState.teams.map(team => {
if (id === team.id) {
team.thumbDown = team.thumbDown + 1;
team.votedDownColor = { color: "#F8004C" };
}
return team;
}),
clickedTeam: id,
downVote: id
};
});
alert.show(`You Down Voted ${id}`);
}
} else {
alert.show("You have already voted.");
}
} else {
alert.show("Please log in first!");
this.props.history.push(`/login`);
}
};
// When user votes, update the db before updating the state
UNSAFE_componentWillUpdate(newProps, newState) {
newState.teams.map(team => {
if (team.id === newState.clickedTeam) {
axios.put(`/api/teams/${newState.clickedTeam}/`, {
id: team.id,
thumbUp: team.thumbUp,
thumbDown: team.thumbDown
});
}
});
}
render() {
// Welcome header message when user logs in
console.log("render", this.state.teams[0].thumbUp);
const { isAuthenticated, user } = this.props.auth;
const { upVote, downVote } = this.state;
const welcome_header = (
<div className="welcome-header">
<h4 style={{ textAlign: "left" }} className="welcome-header-line">
Welcome, {user && user.username}!
</h4>
<h4 style={{ textAlign: "left" }} className="welcome-header-line">
<span>
Your Vote:{" "}
<i className="far fa-thumbs-up up" style={{ color: "#1E95E0" }}></i>
<span style={{ textTransform: "capitalize" }}>{upVote}</span>
</span>{" "}
<span>
<i
className="far fa-thumbs-down down"
style={{ color: "#F8004C" }}
></i>
<span style={{ textTransform: "capitalize" }}>{downVote}</span>
</span>
</h4>
</div>
);
return (
<div className="home">
<div className="home-container">
{isAuthenticated && welcome_header}
<h2>Who Is Your NBA Champion This Year?</h2>
<Teams
upVote={this.state.upVote}
downVote={this.state.downVote}
teams={this.state.teams}
onClickHandler={this.onClickHandler}
/>
</div>
</div>
);
}
}
Home.propTypes = {
update_up: PropTypes.func.isRequired,
update_down: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(mapStateToProps, { update_up, update_down })(
withAlert()(withRouter(Home))
);
When ratings show up
When ratings don't show up
I'm console logging this.state.teams[0] and this.state.teams[0].thumbUp in the render method.
Even during the first render, both thumbUp and thumbDown show in this.state.teams[0], but this.state.teams[0].thumbUp appears to be undefined.
I happened to fix the issue. The issue was actually in the Rating.js file, sorry that I didn't post that file cuz I thought the issue had to be in Home.js.
Before, in Rating.js file, I originally brought in user from redux which caused the issue (I believe it didn't make Rating re-render when in Home.js the axios get call happened after componentWillReceiveProps).
After, instead of bringing in user from redux, I passed user to Rating.js as a prop from Home.js.
Even though it works fine now, I still don't know what exactly the issue was... I'd much appreciate it if someone could enlighten me! Also, please critique my code (i.e. where I can improve)! THANK YOU!
Rating.js (Before)
import React from "react";
import "./Rating.css";
import PropTypes from "prop-types";
import { connect } from "react-redux";
const Rating = props => {
const { thumbUp, thumbDown, id, votedUpColor, votedDownColor } = props.team;
const { upVote, downVote, onClickHandler } = props;
const { user } = props.auth;
let thumbUpColor =
user && id === upVote ? { color: "#1E95E0" } : votedUpColor;
let thumbDownColor =
user && id === downVote ? { color: "#F8004C" } : votedDownColor;
console.log(id, thumbUp, thumbDown);
return (
<div className="rating" key={id}>
<button
className="thumb-up up"
style={thumbUpColor}
onClick={e => onClickHandler(id, e)}
>
<i className="far fa-thumbs-up up"></i>
<span style={{ userSelect: "none" }} className="up">
{thumbUp}
</span>
</button>
<button
className="thumb-down down"
style={thumbDownColor}
onClick={e => onClickHandler(id, e)}
>
<i className="far fa-thumbs-down down"></i>
<span style={{ userSelect: "none" }} className="down">
{thumbDown}
</span>
</button>
</div>
);
};
Rating.propTypes = {
team: PropTypes.object.isRequired,
onClickHandler: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(mapStateToProps)(Rating);
Rating.js (After)
import React from "react";
import "./Rating.css";
import PropTypes from "prop-types";
// import { connect } from "react-redux";
const Rating = props => {
const { thumbUp, thumbDown, id, votedUpColor, votedDownColor } = props.team;
const { upVote, downVote, onClickHandler, user } = props;
// const { user } = props.auth;
let thumbUpColor =
user && id === upVote ? { color: "#1E95E0" } : votedUpColor;
let thumbDownColor =
user && id === downVote ? { color: "#F8004C" } : votedDownColor;
console.log(id, thumbUp, thumbDown);
return (
<div className="rating" key={id}>
<button
className="thumb-up up"
style={thumbUpColor}
onClick={e => onClickHandler(id, e)}
>
<i className="far fa-thumbs-up up"></i>
<span style={{ userSelect: "none" }} className="up">
{thumbUp}
</span>
</button>
<button
className="thumb-down down"
style={thumbDownColor}
onClick={e => onClickHandler(id, e)}
>
<i className="far fa-thumbs-down down"></i>
<span style={{ userSelect: "none" }} className="down">
{thumbDown}
</span>
</button>
</div>
);
};
Rating.propTypes = {
team: PropTypes.object.isRequired,
onClickHandler: PropTypes.func.isRequired
// auth: PropTypes.object.isRequired
};
// const mapStateToProps = state => ({
// auth: state.auth
// });
export default Rating;

React Modal doesn't show up correctly

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.

Hide canvas element for visualSetting in react-mic

I am trying to hide the canvas element in this MyRecorder component:
The element is visible when inspecting the page in browser.
import React, {Component} from 'react';
import { render } from 'react-dom';
import start from '../img/start.svg';
import stop from '../img/stop.svg';
import pause from '../img/pause.svg';
import { ReactMic } from 'react-mic';
class MyRecorder extends Component {
constructor(props){
super(props);
this.state = {
blobObject: null,
isRecording: false,
isPaused: false
}
}
startOrPauseRecording= () => {
const { isPaused, isRecording } = this.state
if(isPaused) {
this.setState({ isPaused: false })
} else if(isRecording) {
this.setState({ isPaused: true })
} else {
this.setState({ isRecording: true })
}
}
stopRecording= () => {
this.setState({ isRecording: false });
}
onStop= (blobObject) => {
this.setState({ blobURL : blobObject.blobURL });
}
render() {
const { blobURL, isRecording, isPaused } = this.state;
const getImage = () => {
if(isRecording && !isPaused) {
return (`url(${pause})`)
}
else {
return (`url(${start})`)
}
}
return(
<div
style={{marginLeft: 15,}}
>
<ReactMic
record={isRecording}
pause={isPaused}
visualSetting="none"
audioBitsPerSecond= {128000}
onStop={this.onStop}
onStart={this.onStart}
onSave={this.onSave}
strokeColor="#000000" />
<audio ref="" controls="controls" src={blobURL}></audio>
<br />
<br />
<button
className="btn btn-light recButton"
style={{
backgroundImage: `url(${isRecording && !isPaused? pause : start})`,
width:40,
height:40,
}}
onClick={this.startOrPauseRecording}>
</button>
<button
className="btn btn-light recButton"
disabled={!isRecording}
style={{
backgroundImage: `url(${stop})`,
width:40,
height:40,
}}
onClick={this.stopRecording}>
</button>
<br />
</div>
);
}
}
export default MyRecorder;
When the visualSetting is:
visualSetting="sinewave"
Sinewaves are shown in the canvas, after changing it to:
visualSetting="none"
The waves go away but the canvas element is still there. Any idea how to get rid of the element?
I was able to find a workaround. In the file node_modules/react-mic/es/components/ReactMic.js
Change line 130 from:
return React.createElement('canvas', { ref: 'visualizer', height: height, width: width, className: this.props.className });
To:
return React.createElement('canvas', { ref: 'visualizer', height: 0, width: 0, className: this.props.className });

Using sweet alert 2 getting this.props is undefined after using Warning alert

I am getting this.props is undefined when using the sweetalert2 warning alert. I am trying to let a user confirm before deleting their profile, but I assume this must be doing something to this.props?
Here is the code. Everything is hooked up to redux correctly as I have other places I am calling this.props and it works just fine, so I will be only placing the function where this is breaking, however if you feel that this post would benefit from having all the code I will make an edit.
the function is called with an onClick event from a button. I have console.log and the button is fully working and calls the function:
<button
className="btn btn-danger btn-lg btn-block"
onClick={this.deleteProfile.bind(this)}
>
DELETE Profile
</button>
To clarify the error message I will add a picture of the console:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import swal from 'sweetalert2/dist/sweetalert2.all.min.js';
import actions from '../../actions';
import { UpdateProfile } from '../view';
import { DateUtils } from '../../utils';
class Profile extends Component {
constructor() {
super();
this.state = {
profile: {
image:
'https://lh3.googleusercontent.com/EJf2u6azJe-TA6YeMWpDtMHAG6u3i1S1DhbiUXViaF5Pyg_CPEOCOEquKbX3U-drH29oYe98xKJiWqYP1ZxPGUQ545k',
bannerImage:
'https://lh3.googleusercontent.com/RAdfZt76XmM5p_rXwVsfQ3J8ca9aQUgONQaXSE1cC0bR0xETrKAoX8OEOzID-ro_3vFfgO8ZMQIqmjTiaCvuK4GtzI8',
firstName: 'First Name',
lastName: 'Last Name',
email: 'Contact Email',
bio: 'Bio will go here'
}
};
}
componentDidMount() {
const { id } = this.props.match.params;
if (this.props.profiles[id] != null) {
return;
}
this.props
.getProfile(id)
.then(() => {})
.catch(err => {
console.log(err);
});
}
createUpdatedProfile(params) {
const { id } = this.props.match.params;
const profile = this.props.profiles[id];
const { currentUser } = this.props.user;
if (currentUser.id !== profile.id) {
swal({
title: 'Oops...',
text: 'You do not own this profile',
type: 'error'
});
return;
}
this.props
.updateProfile(currentUser, params)
.then(response => {
swal({
title: `${response.username} Updated!`,
text: 'Thank you for updating your profile',
type: 'success'
});
})
.catch(err => {
console.log(err);
});
}
deleteProfile() {
const { id } = this.props.match.params;
const profile = this.props.profiles[id];
const { currentUser } = this.props.user;
if (currentUser.id !== profile.id) {
swal({
title: 'Oops...',
text: 'You do not own this profile',
type: 'error'
});
return;
}
swal({
title: 'Are you sure?',
text: 'Your Profile will be lost forever!',
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then(() => {
this.props
.deleteProfile(profile)
.then(() => {
this.props.history.push('/');
swal('Deleted!', 'Your Profile has been deleted.', 'success');
})
.catch(err => {
console.log(err);
});
});
}
render() {
const { id } = this.props.match.params;
const profile = this.props.profiles[id];
const { currentUser } = this.props.user;
const defaultProfile = this.state.profile;
const bannerUrl =
profile == null
? defaultProfile.bannerImage
: profile.bannerImage || defaultProfile.bannerImage;
const bannerStyle = {
backgroundImage: `url(${bannerUrl})`,
backgroundSize: '100%',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center'
};
const nameStyle = {
background: 'rgba(255, 255, 255, 0.7)',
borderRadius: '8px'
};
const imageStyle = {
maxHeight: '150px',
margin: '20px auto'
};
return (
<div>
{profile == null ? (
<div>
<h1>Profile no longer exists</h1>
</div>
) : (
<div>
<div className="jumbotron jumbotron-fluid" style={bannerStyle}>
<div className="container" style={nameStyle}>
<img
src={profile.image || defaultProfile.image}
style={imageStyle}
className="rounded img-fluid mx-auto d-block"
/>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<h1 className="display-3 text-center">{profile.username}</h1>
<p className="lead text-center">
{profile.firstName || defaultProfile.firstName}{' '}
{profile.lastName || defaultProfile.lastName}
</p>
<p className="lead text-center text-muted">
{profile.email || defaultProfile.email}
</p>
<p className="text-center text-muted">
User since: {DateUtils.relativeTime(profile.timestamp)}
</p>
<hr className="my-4" />
<p className="lead" style={{ border: '1px solid #e6e6e6', padding: '20px' }}>
{profile.bio || defaultProfile.bio}
</p>
</div>
</div>
{currentUser == null ? null : currentUser.id !== profile.id ? null : (
<div>
<UpdateProfile
currentProfile={profile}
onCreate={this.createUpdatedProfile.bind(this)}
/>
<div className="row justify-content-center" style={{ marginBottom: '100px' }}>
<div className="col-sm-6">
<button
className="btn btn-danger btn-lg btn-block"
onClick={this.deleteProfile.bind(this)}
>
DELETE Profile
</button>
</div>
</div>
</div>
)}
</div>
)}
</div>
);
}
}
const stateToProps = state => {
return {
profiles: state.profile,
user: state.user
};
};
const dispatchToProps = dispatch => {
return {
getProfile: id => dispatch(actions.getProfile(id)),
updateProfile: (currentUser, params) => dispatch(actions.updateProfile(currentUser, params)),
deleteProfile: entity => dispatch(actions.deleteProfile(entity))
};
};
export default connect(stateToProps, dispatchToProps)(Profile);
Try to bind your deleteProfile function to the class in the constructor using
this.deleteProfile = this.deleteProfile.bind(this);
Or you can change the definition of the function and use an arrow function to define it.
deleteProfile=()=>{
... //rest of function body
}
and remove the bind from the onClick handler

Resources