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
Related
I try to learn React JS, however, I stumbled over a problem I can't solve. I try to use an API to get a value of something and show the value as a simple text, but the text is not updating even tho the Data gets correctly log in console.
The Code of my App.js is
import React, { Component } from "react";
import { Button } from "#material-ui/core";
import { Image } from "react-bootstrap";
import albedo from "#albedo-link/intent/lib/albedo.intent";
import albedologo from "./albedo.png";
class LogInWithAlbedo extends Component {
constructor(props) {
super(props);
this.state = {
value: null
};
}
Albedo() {
albedo.publicKey({}).then((res) => {
const { intent, pubkey, signature, signed_message } = res;
console.log({ intent, pubkey, signature, signed_message });
this.setState((currentState) => {
return { value: pubkey };
});
});
}
render() {
const { pubkey } = this.state;
return (
<div>
<div>
<Button
style={{ width: "207px", height: "40px" }}
variant="contained"
color="default"
onClick={this.Albedo.bind(this)}
>
Login With <Image style={{ width: "55px" }} src={albedologo} />
</Button>
<h2>It is {pubkey}.</h2>
</div>
</div>
);
}
}
export default LogInWithAlbedo;
You can also see it here:
https://codesandbox.io/s/vigilant-star-ntqv7
I'm also using semantic-ui-react. When I pass the child component down from the parent the css styling gets all messed up, I lose my images and the click doesn't work.
I can call the cardClickHandler method in the parent component and am console logging the correct child, i just can't get it to render (am not hitting the console.log in the child component).
I also tried to run the cardClickHandler method in the images container to pass it down but that didn't work.
please help and explain what i'm doing wrong. thanks!
images container:
import React from 'react';
import SearchBar from '../components/SearchBar';
import Images from '../components/Images';
import ImageCard from '../components/ImageCard';
class ImagesContainer extends React.Component {
state = {
images: [],
image: {},
sortValue: '',
inputValue: '',
};
componentDidMount() {
fetch('http://localhost:3000/images').then((resp) => resp.json()).then((resp) => {
this.setState({
images: resp
});
});
}
imageFilterOnChange = (event) => {
this.setState({
inputValue: event.target.value
});
};
sortImages = (images) => {
if (this.state.sortValue === 'location') {
return [ ...images ].sort((a, b) => {
if (a.location > b.location) {
return 1;
} else if (a.location < b.location) {
return -1;
} else {
return 0;
}
});
} else {
return images;
}
};
render() {
const filteredImages = this.state.images.filter((image) => {
return image.location.toLowerCase().includes(this.state.inputValue.toLowerCase());
});
return (
<div>
<Images
images={this.sortImages(filteredImages)}
onClick={this.cardClickHandler}
/>
<SearchBar
images={this.sortImages(filteredImages)}
imageFilterOnChange={this.imageFilterOnChange}
inputValue={this.state.inputValue}
onChange={this.handleSortImages}
/>
</div>
</div>
);
}
}
export default ImagesContainer;
parent component:
import React from 'react';
import ImageCard from './ImageCard';
import { Card, Image } from 'semantic-ui-react';
class Images extends React.Component {
state = {
image: []
};
cardClickHandler = (e) => {
let cardId = e.target.dataset.id;
this.props.images.find((image) => {
return image.id === cardId;
});
console.log('hi, cardId', cardId);
fetch(`http://localhost:3000/images/${cardId}`)
.then((resp) => resp.json())
.then((resp) => {
this.setState({
image: resp
})
console.log(this.state.image);
})
}
render() {
const allImages = this.props.images;
return allImages.map((image) => {
return (
<Card
key={image.id}
className="photo"
data-id={image.id}
data-name={image.name}
onClick={this.cardClickHandler}
>
<img
src={image.image}
alt=""
data-id={image.id}
data-name={image.name}
className="photo-image"
height={265}
/>
</Card>
);
});
}
}
export default Images;
child component:
i'm not hitting the console.log here, so no more code!
import React from 'react';
import { Card, Image } from 'semantic-ui-react';
class ImageCard extends React.Component {
render() {
console.log('image card');
return (
<Card>
</Card>
);
}
}
export default ImageCard;
I left a comment with a few improvements to the code you could make. Specifically:
You have an extra </div> in your ImagesContainer.
Also, you'll want to remove onClick={this.cardClickHandler} from ImagesContainer as cardClickHandler is defined not on ImagesContainer but instead on your Images component.
But the problem is that you are not rendering your ImageCard component at all. You are just rendering <Card> instead of <ImageCard>
Specifically, your parent component's render should change from this:
render() {
const allImages = this.props.images;
return allImages.map((image) => {
return (
<Card
key={image.id}
className="photo"
data-id={image.id}
data-name={image.name}
onClick={this.cardClickHandler}
>
<img
src={image.image}
alt=""
data-id={image.id}
data-name={image.name}
className="photo-image"
height={265}
/>
</Card>
);
});
}
to this:
render() {
const allImages = this.props.images;
return allImages.map((image) => {
return (
<ImageCard
key={image.id}
className="photo"
data-id={image.id}
data-name={image.name}
onClick={this.cardClickHandler}
>
<img
src={image.image}
alt=""
data-id={image.id}
data-name={image.name}
className="photo-image"
height={265}
/>
</ImageCard>
);
});
}
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
});
I'm using the official Semantic UI React components to create a web application. I have a form on a search page, which contains an input field.
import React from 'react'
import {Form} from "semantic-ui-react";
import RadiusOfSearchInput from "./RadiusOfSearchInput";
const NearbyShopsSearchForm = (props) => {
const { onSubmit, size, action, onChange, value, style } = props
return (
<Form onSubmit={onSubmit}>
<RadiusOfSearchInput size={size}
action={action}
onChange={onChange}
value={value}
style={style} />
</Form>
)
}
export default NearbyShopsSearchForm
The component that uses the form is as shown below:
import React, { Component } from 'react'
import {Menu, Container, Segment} from 'semantic-ui-react'
import ShopCardList from "../components/ShopCardList";
import axios from 'axios';
import NearbyShopsSearchForm from "../components/NearbyShopsSearchForm";
class NearbyShopsPage extends Component {
constructor(props) {
super(props)
this.state = {
radius: '',
shops: []
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange = (e, { value } ) => {
this.setState({ radius: value })
}
handleSubmit = (e, data) => {
const { radius } = this.state
const url = `/api/shops/#33.846978,-6.775816,${radius}`
axios.get(url)
.then((response) => {
this.setState({ shops: response.data })
})
.catch((error) => {
console.log(error)
})
e.preventDefault()
}
render() {
const { radius } = this.state
return (
<Segment basic>
<Menu fixed='top' size='huge' borderless>
<Menu.Item>
<NearbyShopsSearchForm onSubmit={this.handleSubmit}
size='large'
action={{ color: 'teal', content: 'Search', size: 'small' }}
onChange={this.handleChange}
value={radius}
style={{ width: '17.5em' }} />
</Menu.Item>
</Menu>
<Container style={{ marginTop: '5.5em' }}>
<ShopCardList shops={this.state.shops}/>
</Container>
</Segment>
)
}
}
export default NearbyShopsPage
I want to validate the form so it won't submit values other than decimals, which are valid values to represent a distance. I didn't find validation support in the SUIR official documentation. I'm aware of the redux-form possibility, but i fail to implement it correctly. what's the recommended and simplest way to implement the data validation feature?
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...