I'm using ReactJS (and nodejs, mongodb..) and I have projects with the delete option and I want to show a delete alert confirm window and I'm using SweetAlert for the first time. It shows the SweetAlert but doesn't let me choose the option, delete the project immediately. I'll show a gif so you can see what is happening.
Thank you!
My ProjectPage Component:
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import moment from 'moment';
import SweetAlert from 'react-bootstrap-sweetalert'
import Tasks from '../../TaskList/Tasks/Tasks';
import './ProjectPage.css';
class ProjectPage extends Component {
constructor(props) {
super(props);
this.state = {
project: {},
alert: null
};
}
componentDidMount() {
const { match: { params } } = this.props;
fetch(`/dashboard/project/${params.id}`)
.then(response => {
return response.json()
}).then(project => {
this.setState({
project: project
})
})
}
deleteProject(e){
const getAlert = () => (
<SweetAlert
warning
showCancel
confirmBtnText="Yes!"
confirmBtnBsStyle="danger"
cancelBtnBsStyle="default"
title="Are you sure you want to delete this project?"
onConfirm={() => this.deleteFile()}
onCancel={() => this.onCancelDelete()}
>
You will not be able to recover this project!
</SweetAlert>
);
this.setState({
alert: getAlert()
});
e.preventDefault();
}
onCancelDelete(){
this.setState({
alert: null
});
}
render() {
const { match: { params } } = this.props;
const BackgroundImage = {
backgroundImage: `url(${this.state.project.imageURL})`,
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'center',
height: '350px',
opacity: '0.7'
}
return (
<div>
<header style={BackgroundImage}>
[...]
<form method='POST' action={`/dashboard/project/${params.id}/delete?_method=DELETE`}>
<button id='button__project-delete' style={{ boxShadow: 'none' }} className='button__options--project btn btn-outline-secondary'
type='submit' onClick={() => this.deleteProject()}>Delete</button> {this.state.alert}
</form>
</header>
[...]
</div>
);
}
}
export default ProjectPage;
GIF what's happening:
It looks your page refreshed on button click, because it is inside a form object. On button click, click event can not be accessible. So e.preventDefault() does not work.
You have to pass event object to deleteProject() method.
Change this line
<button id='button__project-delete' style={{ boxShadow: 'none' }} className='button__options--project btn btn-outline-secondary'
type='submit' onClick={() => this.deleteProject()}>Delete</button> {this.state.alert}
to
<button id='button__project-delete' style={{ boxShadow: 'none' }} className='button__options--project btn btn-outline-secondary'
type='submit' onClick={(e) => this.deleteProject(e)}>Delete</button> {this.state.alert}
this.setState({
alert: getAlert()
});
Please check after changing this to
this.setState({
alert: getAlert
});
Related
Hi I am trying to create a simple popup box showing a validation Text and input field, the user needs to insert some text into the input for confirmation, then click "Confirm" appon clicking confirm a function will be executed.
the confirmation component will receive this props:
isOpen - boolean,
msg - string,
executableFunction - function
this three props will be received via Redux Store because this component is shared by many other components I placed it at my app.js file.
I tested it in a small example and it works, but when I tried to implement it for real I got this error:
"
VM594 react_devtools_backend.js:6 Application state or actions payloads are too large making Redux DevTools serialization slow and consuming a lot of memory. See https://git.io/fpcP5 on how to configure it.
"
I imagine the executable function is too big, its a function that make a http post request to a server gets a response back and make changes to a component (basically show to the user the result of the execution...).
is there a way around this problem ? what am I doing wrong ?
the confirmation component:
import React, { useState } from "react";
import {connect} from "react-redux";
import { setConfirmation } from '../../../actions/sharedComponentsAction';
import PropTypes from "prop-types";
import { toastr } from "react-redux-toastr";
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import Backdrop from '#material-ui/core/Backdrop';
import Fade from '#material-ui/core/Fade';
import {handleChange} from "../../functionUtils/FunctionsUtils";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
const useStyles = makeStyles((theme) => ({
modal: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
paper: {
backgroundColor: theme.palette.background.paper,
border: '2px solid #000',
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
textField: {
width: '400px',
marginTop: theme.spacing(2),
marginBottom: theme.spacing(6),
},
button: {
width: 120,
},
}));
const ConfirmationPopupValidateXXX = ({ selectedClient, setConfirmation, isOpen ,message, validationHelperText, executableFunction }) => {
const { XXX } = selectedClient.value;
const [InputtedXXX, setInputtedXXX] = useState('');
const handleClose = async () => {
await console.log('handleClose Called');
await setConfirmation(false);
};
const validateAndExecuteFunction = () => {
console.log('validateAndExecuteFunction called');
if ( XXX !== InputtedXXX )
{
toastr.error('XXX Name Doesnt Equal Selecte Client\'s XXX');
return;
}
executableFunction();
handleClose();
};
const classes = useStyles();
return (
<div>
<Modal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
className={classes.modal}
open={isOpen}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={isOpen}>
<div className={classes.paper + ' material-ui'}>
<div>
<h3>Confirmation Required</h3>
<div style={{whiteSpace: 'pre-wrap'}}>
{message}
</div>
</div>
<TextField
label="XXX Name"
helperText={validationHelperText}
className={classes.textField}
value={InputtedXXX}
onChange={handleChange(setInputtedXXX)}
margin="normal"
/>
<div className={'flex-space'} style={{textAlign: 'right'}}>
<Button className={classes.button} variant="contained" color="primary" onClick={ handleClose }>
CANCEL
</Button>
<Button className={classes.button} disabled={InputtedXXX === ''} variant="contained" color="primary" onClick={ validateAndExecuteFunction }>
CONFIRM
</Button>
</div>
</div>
</Fade>
</Modal>
</div>
);
};
ConfirmationPopupValidateXXX.defaultProps = {
validationHelperText: 'Type the XXX name to confirm creation',
};
ConfirmationPopupValidateXXX.prototypes = {
selectedClient: PropTypes.object.isRequired,
setConfirmation: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
message: PropTypes.string,
validationHelperText: PropTypes.string,
executableFunction: PropTypes.func.isRequired,
};
const mapStateToProps = state => ({
selectedClient: state.client.selectedClient,
});
export default connect(mapStateToProps, { setConfirmation })(ConfirmationPopupValidateXXX);
This is how I added the confirmation box to app.js
{ isConfirmationOpen &&
<ConfirmationPopupValidateXXX
isOpen={isConfirmationOpen}
message={confirmationMessage}
validationHelperText={confirmationValidationHelperText}
executableFunction={confirmationExecutableFunction}
/>
}
await setConfirmation(true, msg, functionToExecute); // setConfirmation will dispatch this three variables to the store where ConfirmationPopupValidateXXX will use them
const functionToExecute = async () => {
// call server
// get response
// useState - change component state add response Message so the client can see what is the response of the action he performed
};
im new in react and well im trying to pass a value from a card click to a child component, i tried a lot of different options but is not working.... can please someone give me a hand with this.
Parent :
import React, { Component } from 'react';
import {
Card, CardImg, CardBody,
CardTitle
} from 'reactstrap'; import { Container, Dimmer, Loader } from 'semantic-ui-react'
import logo from './santa.png'
import Divisiones from './division';
class divisionesSisa extends Component {
constructor() {
super()
this.state = {
division: "1"
}
this.methodFetch = this.methodFetch.bind(this)
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
this.methodFetch()
}
fetch(endpoint) {
return window.fetch(endpoint)
.then(response => response.json())
.catch(error => console.log(error))
}
methodFetch() {
this.fetch('/####')
.then(results => {
return results;
}).then(data => {
this.setState(data)
})
}
handleClick = (e) =>{
this.setState({ division: e.target.id });
}
render() {
let { data } = this.state
return data
?
<div className="row">
{Object.keys(data).map((key) => {
return <div className="col-md-2">
<Card>
<CardImg style={{ justifyContent: 'center', alignItems: 'center', marginLeft: 0, marginRight: 1 }} src={logo} alt="Card image cap" />
<CardBody style={{ marginBottom: 10, marginLeft: 0, marginRight: 0 }}>
<a id={data[key]} href="sisa/division" onClick={() => this.handleClick}><CardTitle align="center" >{data[key]}</CardTitle></a>
</CardBody>
</Card>
</div>
})}
<Divisiones division={this.handleClick.bind(this)}/>
</div>
: <Container text>
<Dimmer active inverted>
<Loader content='Loading' />
</Dimmer>
</Container>
}
}
export default divisionesSisa;
Child component
import React, { Component } from 'react';
class division extends Component {
constructor(props){
super(props)
}
componentDidMount(){
console.log(this.props.division)
}
show(){
}
render() {
return(
<div>
<h2>{this.props.division}</h2>
</div>
);
}
}
export default division;
what im doing wrong?
i take any suggestions to fix this problem or change the way im using react
I believe you should use the state to set division prop in 'Divisiones'
const { division } = this.state
<Divisiones division={ division }
[Edit]
As you are receiving 'undefined', I have noticed that you don't pass event to your handleClick function.
You are expecting an event parameter here:
handleClick = (e) => {
this.setState({ division: e.target.id });
}
So you should pass the parameter like this:
onClick={(event) => this.handleClick(event)}
plus you could also add a onClick function on the CardImg
i'm using react JS for front end and .NET API for backend , i'm trying to fetch data from API , i enabled CORS (i added some configuration in startup file ) and it's all fine normally .
in react js , i want to fetch data using my API so this is my code to show a list of data :
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import { List, Avatar, Button, Spin } from "antd";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import reqwest from "reqwest";
const fakeDataUrl =
"http://localhost:51492/api/experience/";
class LoadMoreList extends React.Component {
state = {
loading: true,
loadingMore: false,
showLoadingMore: true,
data: []
};
componentDidMount() {
this.getData(res => {
this.setState({
loading: false,
data: res.results
});
});
}
getData = callback => {
reqwest({
url: fakeDataUrl,
type: "json",
method: "get",
contentType: "application/json",
success: res => {
callback(res);
}
});
};
onLoadMore = () => {
this.setState({
loadingMore: true
});
this.getData(res => {
const data = this.state.data.concat(res.results);
this.setState(
{
data,
loadingMore: false
},
() => {
// Resetting window's offsetTop so as to display react-virtualized demo underfloor.
// In real scene, you can using public method of react-virtualized:
// https://stackoverflow.com/questions/46700726/how-to-use-public-method-updateposition-of-react-virtualized
window.dispatchEvent(new Event("resize"));
}
);
});
};
render() {
const { loading, loadingMore, showLoadingMore, data } = this.state;
const loadMore = showLoadingMore ? (
<div
style={{
textAlign: "center",
marginTop: 12,
height: 32,
lineHeight: "32px"
}}
>
{loadingMore && <Spin />}
{!loadingMore && (
<Button onClick={this.onLoadMore}>loading more</Button>
)}
</div>
) : null;
return (
<List
style={{
width: "50%",
left: "25%"
}}
className="demo-loadmore-list"
loading={loading}
itemLayout="horizontal"
loadMore={loadMore}
dataSource={data}
renderItem={item => (
<List.Item
actions={[
<Button type="primary" icon="user-add">
suivre
</Button>,
<a>Message</a>
]}
>
<List.Item.Meta
avatar={
<a>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />{" "}
</a>
}
title={{item.titre}}
/>
</List.Item>
)}
/>
);
}
}
LoadMoreList.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles()(LoadMoreList);
this code will show a list of experiences and it allows us to load more data clicking on LoadMore
but what i get when i start the project :
and in DevTools i get this error
Failed to load resource: net::ERR_CONNECTION_REFUSED
i looked in google for many solutions but no one helped me
thanks for helping me .
i'm new in react js and i'm trying to fetch data from My API , which i can its result with POSTMAN , and it shows the data
My problem is when i use the link :" http://localhost:51492/api/user/1 " in my react js app , data couldn't appear ...
PS : je travail avec Code SandBox
here is my code showing all the followers of a user :
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import { List, Avatar, Button, Spin } from "antd";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import reqwest from "reqwest";
const fakeDataUrl =
"http://localhost:51492/api/follower/all/1";
class LoadMoreList extends React.Component {
state = {
loading: true,
loadingMore: false,
showLoadingMore: true,
data: []
};
componentDidMount() {
this.getData(res => {
this.setState({
loading: false,
data: res.results
});
});
}
getData = callback => {
reqwest({
url: fakeDataUrl,
type: "json",
method: "get",
contentType: "application/json",
success: res => {
callback(res);
}
});
};
onLoadMore = () => {
this.setState({
loadingMore: true
});
this.getData(res => {
const data = this.state.data.concat(res.results);
this.setState(
{
data,
loadingMore: false
},
() => {
// Resetting window's offsetTop so as to display react-virtualized demo underfloor.
// In real scene, you can using public method of react-virtualized:
// https://stackoverflow.com/questions/46700726/how-to-use-public-method-updateposition-of-react-virtualized
window.dispatchEvent(new Event("resize"));
}
);
});
};
render() {
const { loading, loadingMore, showLoadingMore, data } = this.state;
const loadMore = showLoadingMore ? (
<div
style={{
textAlign: "center",
marginTop: 12,
height: 32,
lineHeight: "32px"
}}
>
{loadingMore && <Spin />}
{!loadingMore && (
<Button onClick={this.onLoadMore}>loading more</Button>
)}
</div>
) : null;
return (
<List
style={{
width: "50%",
left: "25%"
}}
className="demo-loadmore-list"
loading={loading}
itemLayout="horizontal"
loadMore={loadMore}
dataSource={data}
renderItem={item => (
<List.Item
actions={[
<Button type="primary" icon="user-add">
suivre
</Button>,
<a>Message</a>
]}
>
<List.Item.Meta
avatar={
<a>
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />{" "}
</a>
}
title={{item.userProfile}}
/>
</List.Item>
)}
/>
);
}
}
LoadMoreList.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles()(LoadMoreList);
and here is what PostMan shows when i enter the URL : http://localhost:51492/api/follower/all/1
what i thinks is missing is the "results attribute" at the beginning of the result in postman , i think it must be like that :
please help me , and thank u for ur interest
I am new to react. I am displaying 10 question with 3 answers per question. Im having trouble capturing which answers they choose per question and storing the value as a array. Here is my code. Im not sure but I think i will need a handle change and a handle submit and bind them to the answers.
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from 'react-router-dom';
import axios from 'axios';
import AnswerOption from "./answersContent";
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
const styles = {
display: 'flex',
justifyContent: "center"
};
const style = {
margin: 15,
};
const Content = {
padding: 10,
margin: 10,
backgroundColor: "",
color: "",
display: "inline-block",
fontFamily: "monospace",
fontSize: "18",
};
const answ ={
listStyle: 'none'
};
class Questions extends Component {
constructor(props) {
super(props);
this.state = {
redirect: "",
user: "",
questions: [],
answers: []
}
}
componentDidMount() {
console.log(this.props.user);
axios.post('/questions')
.then((response) => {
console.log(response);
if (response.status === 200) {
console.log("successfull");
// self.setState({ user: response.data.user.id});
this.setState({user: this.props.user});
this.setState({redirect: false});
this.setState ({ questions :
response.data.surveyQuestions})
}
})
.catch(function (error) {
console.log(error);
});
}
handleClick(event){
const payload={
"answers": this.state.answers
};
console.log(payload)
}
render(){
const { redirect } = this.state;
if (redirect) {
return <Redirect to='/login'/>;
}
return (
<div className="dashboard" style={styles}>
< MuiThemeProvider>
<div style={Content}>
<h1>Welcome to The Well-Stocked Stork!</h1>
<br />
{this.state.questions.map((quest) => (
<p> {quest.id}. {quest.question}
<ul style={answ}>
<li> <input type="radio" name=
{quest.surveyAnswers[0].body} value={quest.surveyAnswers[0].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[0].value})} />{quest.surveyAnswers[0].body}</li>
<li> <input type="radio" name=
{quest.surveyAnswers[1].body} value={quest.surveyAnswers[1].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[1].value})} />{quest.surveyAnswers[1].body}</li>
<li> <input type="radio" name=
{quest.surveyAnswers[2].body} value={quest.surveyAnswers[2].value}
onChange = {(event,value) => this.setState({answers:
quest.surveyAnswers[2].value})} />{quest.surveyAnswers[2].body}</li>
</ul>
</p>
))}
<RaisedButton label="Submit" primary={true} style=
{style} onClick={(event) => this.handleClick(event)}/>
</div>
</MuiThemeProvider>
</div>
)
}
}
export default Questions;
You are right to handle change but you are missing one thing. You should bind you handleClick method in the constructor. Something like this.handleClick = this.handleClick.bind(this) otherwise you will get an error something ..state is not defined...