Why is this.prop not updating? - reactjs

I have a parent component, that dynamically creates child components, and works great. But as part of that child component, I'm trying to open a modal with a button click, yet the button doesn't work.
To me it seems like that the this.props.lgShow isn't getting the state change. How do I make sure of that?
Here's my parent component:
import React, { Component, Fragment } from 'react';
import Button from 'react-bootstrap/Button';
import Policy from './Policy/Policy';
import PolicyButton from './PolicyButton/PolicyButton';
class Handbook extends Component {
constructor(props){
super(props);
this.state = {
clients: [],
policies: [],
usedPolicies: [],
client: 'Choose Client',
logo: '',
color1: '#000',
color2: '#fff',
lgShow: 'false' // show modal toggle
};
this.modalOpen = this.modalOpen.bind(this);
this.modalClose = this.modalClose.bind(this);
this.modalSave = this.modalSave.bind(this);
}
componentDidMount() {
fetch('/api/themes/all')
.then(res => res.json())
.then((result) => {
this.setState({ clients: result });
console.log(result);
})
.then(
fetch(`/api/policy/all`)
.then(res => res.json())
.then((result) => {
this.setState({ policies: result });
console.log(result);
})
);
}
handleDeletePolicy = policyId => {
console.log(`Button clicked: ` + policyId);
for (var i = 0; i < this.state.usedPolicies.length; i++) {
if (this.state.usedPolicies[i].id === policyId) {
const policies = this.state.policies;
const usedPolicies = this.state.usedPolicies;
policies.push(usedPolicies[i]);
this.setState({ policies: policies });
usedPolicies.splice(i, 1);
this.setState({ usedPolicies: usedPolicies });
console.log(this.state.policies);
console.log(this.state.usedPolicies);
}
}
}
modalOpen = policyId => {
console.log("Open Modal" + policyId);
this.setState({lgShow: true});
}
modalClose = policyId => {
console.log("Close Modal" + policyId);
this.setState({ lgShow: false });
}
modalSave = policyId => {
console.log("Save Modal" + policyId);
this.setState({ lgShow: false });
}
render(){
return(
<Fragment>
<div className='policies'>
{this.state.usedPolicies.map(policy => (
<Policy key={policy.id} id={policy.id} policy={policy.policy} contents={policy.contents} color1={this.state.color1} color2={this.state.color2} onDeletePolicy={this.handleDeletePolicy} onOpen={this.modalOpen} onClose={this.modalClose} onSave={this.modalSave} />
))}
</div>
</Fragment>
);
}
}
export default Handbook;
And here is my child component.. I believe the problem must be here somewhere.
import React, { Component } from 'react';
import styled from 'styled-components';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import TinyEditor from '../../TinyEditor/TinyEditor';
const Div = styled.div `
background-color: white;
color: black;
margin-top: 2em;
.edit{
text-align: right;
svg{
font-size: 1em;
margin: 0.25em;
}
}
.policy{
border: 1px solid black;
padding: 2em;
}
h1{
margin-bottom: 1em;
text-align: left;
padding: .25em;
}
`
class Policy extends Component {
constructor(props){
super(props);
this.state = {
id: this.props.id,
policy: this.props.policy,
contents: this.props.contents,
color1: this.props.color1,
color2: this.props.color2,
lgShow: this.props.lgShow
}
}
render(){
return(
<Div className="container">
<div className="edit">
<Button variant="light" onClick={() => this.props.onOpen(this.props.id)}><i className="far fa-edit"></i></Button>
<Button variant="light" onClick={() => this.props.onDeletePolicy(this.props.id)}><i className="far fa-trash-alt"></i></Button>
</div>
<div className="policy">
<h1 style={{ background: this.props.color1, color: this.props.color2 }}>{this.props.policy}</h1>
<div dangerouslySetInnerHTML={{ __html: this.props.contents }}></div>
</div>
<Modal
size="lg"
show={this.props.lgShow}
onHide={this.props.onClose}
aria-labelledby="modal-title-lg"
>
<Modal.Header closeButton>
<Modal.Title id="modal-title-lg">
Large Modal
</Modal.Title>
</Modal.Header>
<Modal.Body>
<TinyEditor />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.props.onClose}>
Close
</Button>
<Button variant="primary" onClick={this.props.onSave}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Div>
)
}
}
export default Policy;

I do not see 'lgShow' property in the 'Policy' tag.
<Policy
key={policy.id}
id={policy.id}
policy={policy.policy}
contents={policy.contents}
color1={this.state.color1}
color2={this.state.color2}
onDeletePolicy={this.handleDeletePolicy}
onOpen={this.modalOpen}
onClose={this.modalClose}
onSave={this.modalSave}
/>
In the child element 'Policy' you wrote:
this.state = {
id: this.props.id,
policy: this.props.policy,
contents: this.props.contents,
color1: this.props.color1,
color2: this.props.color2,
lgShow: this.props.lgShow // This one is not in parent element
}

Related

There is two button, once click on the button the name of the button will render inside the id

Hi guys help me on this i am stuck for a project.
After the button click, the page should look like:
Example
Once click on the button the bellow text will call the color name just like the image
class ColorChange extends Component {
constructor(props) {
super(props);
this.state =
}
render() {
return null;
}
}
class App extends Component {
state = {
text: ''
}
onDocumentClick = (event) => {
if (event.target.tagName === 'BUTTON') {
this.setState({ text: event.target.textContent })
}
}
componentDidMount() {
document.addEventListener('click', this.onDocumentClick)
}
componentWillUnmount() {
document.removeEventListener('click', this.onDocumentClick)
}
render() {
return <div>
{this.props.children}
<Tooltip text={this.state.text}/>
</div>
}
}
<button id="btnGreen">Green</button>
<button id="btnRed">Red</button>
document.getElementById("button2").click();
You can use this code:
import { Component } from "react";
export default class App extends Component {
state = {
text: ""
};
render() {
return (
<div className="App">
<button
style={{
backgroundColor: "green",
color: "white",
cursor: "pointer"
}}
onClick={() => this.setState({ text: "GREEN" })}
>
GREEN
</button>
<button
style={{ backgroundColor: "red", color: "white", cursor: "pointer" }}
onClick={() => this.setState({ text: "RED" })}
>
RED
</button>
<br />
COLOR: {this.state.text}
</div>
);
}
}
You can take a look at this sandbox for a live working example.

Menu items are not clickable after rendering Google Maps container

My semantic-ui-react Menu component is acting strange when I add my google maps component to be rendered. Before I added my MapContainer, the FilterSection was working pretty fine. But after I render the MapContainer my sections in my Menu are no longer clickable nor do they react to my mouse hover. What should I do?
Snippet of render:
return (
<div>
<Navbar/>
<FilterSection/>
<ChatWidget/>
<div className="map-and-cards">
<MapContainer/> // This line causes the problem
<div style={containerStyle} className="cards-container">
<div class="card-columns" style={{gridTemplateColumns: '350px 350px', display: 'grid', rowGap: '50px', columnGap: '18px'}}>
<Cards listingData={listingData}/>
</div>
</div>
</div>
</div>
)
and my MapContainer.js:
import React from 'react';
import { Map, GoogleApiWrapper } from 'google-maps-react';
const style = {
position: 'relative',
top: '65px',
width: '47.5%', // 47.5
height: '85%',
};
const defaultCenter = {
lat: 41.04137, lng: 28.979530
}
export class MapContainer extends React.Component<MapProps> {
render() {
return (
<Map
style = {style}
google={this.props.google}
centerAroundCurrentLocation={true}
zoom={12}
initialCenter={defaultCenter}
/>
);
}
}
export default GoogleApiWrapper({
apiKey: (0)
})(MapContainer)
FilterSection.js:
import React, { Component } from "react";
import { Menu, Dropdown, Input, Button } from "semantic-ui-react";
import 'semantic-ui-css/semantic.min.css'
export class Price extends Component {
state = { isOpen: false };
handleItemClick = (e, { name }) => this.setState({ activeItem: name });
render() {
const { activeItem } = this.state;
return (
<div style={{float: 'left'}}>
<Menu secondary >
<Menu.Item>
<Dropdown
text={"Price"}
className="item"
onClick={this.toggleOpen}
open={this.state.isOpen}
>
<Dropdown.Menu onClick={this.preventClosing}>
<Dropdown.Header icon="money" content={" Price Range"} />
<Dropdown.Divider />
<form
style = {{margin: '10px'}}
name="id"
type="number"
max={900}
action={<Button onClick={this.toggleOpen} content={"Send"} />}
>
<Input style={{zoom: '0.9'}} placeholder="min"/> — <Input style={{zoom: '0.9'}} placeholder="max"/>
</form>
</Dropdown.Menu>
</Dropdown>
</Menu.Item>
</Menu>
</div>
);
}
toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });
preventClosing = e => e.stopPropagation();
}
export class BedsAndBaths extends Component {
state = { isOpen: false };
handleItemClick = (e, { name }) => this.setState({ activeItem: name });
render() {
const { activeItem } = this.state;
return (
<div style={{float: 'left'}}>
<Menu secondary>
<Menu.Item>
<Dropdown
text={"Bedrooms & Livingrooms"}
className="item"
onClick={this.toggleOpen}
open={this.state.isOpen}
>
<Dropdown.Menu onClick={this.preventClosing}>
<form
style = {{margin: '10px'}}
name="id"
type="number"
max={900}
action={<Button onClick={this.toggleOpen} content={"Send"} />}
>
<Input style={{zoom: '0.9'}} placeholder="3"/> + <Input style={{zoom: '0.9'}} placeholder="1"/>
</form>
</Dropdown.Menu>
</Dropdown>
</Menu.Item>
</Menu>
</div>
);
}
toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });
preventClosing = e => e.stopPropagation();
}
export class More extends Component {
state = { isOpen: false };
handleItemClick = (e, { name }) => this.setState({ activeItem: name });
render() {
const { activeItem } = this.state;
return (
<div style={{float: 'left'}}>
<Menu secondary>
<Menu.Item>
<Dropdown
text={"More"}
className="item"
onClick={this.toggleOpen}
open={this.state.isOpen}
>
<Dropdown.Menu onClick={this.preventClosing}>
<Dropdown.Header icon="money" content={" Price Range"} />
<Dropdown.Divider />
<form
style = {{margin: '10px'}}
name="id"
type="number"
max={900}
action={<Button onClick={this.toggleOpen} content={"Send"} />}
>
<Input style={{zoom: '0.9'}} placeholder="min"/> — <Input style={{zoom: '0.9'}} placeholder="max"/>
</form>
</Dropdown.Menu>
</Dropdown>
</Menu.Item>
</Menu>
</div>
);
}
toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });
preventClosing = e => e.stopPropagation();
}
export class Alert extends Component {
state = { isOpen: false };
handleItemClick = (e, { name }) => this.setState({ activeItem: name });
render() {
const { activeItem } = this.state;
return (
<div style={{float: 'left', position: 'relative', top: '11.5px', left: '15px', zoom: '0.9'}}>
<Menu secondary >
<button class="ui button ">
Create Alert
</button>
</Menu>
</div>
);
}
toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });
preventClosing = e => e.stopPropagation();
}
export class Search extends Component {
state = { isOpen: false };
handleItemClick = (e, { name }) => this.setState({ activeItem: name });
render() {
const { activeItem } = this.state;
return (
<div style={{float: 'left', position: 'relative', top: '12px', right: '50px', zoom: '0.9'}}>
<Menu secondary >
<div style={{float: 'left', position: 'relative', right: '10px'}} class="ui input focus">
<input type="text" placeholder="Enter an adress, neigborhood, city, or ZIP code
" size="45"/>
</div>
<button class="ui button ">
Search
</button>
</Menu>
</div>
);
}
toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });
preventClosing = e => e.stopPropagation();
}
export default function FilterSection(){
return (
<div style={{position: 'relative', left: '75px', bottom: '1px'}}><Search/><div style={{position: 'relative', right: '30px'}}><More/><BedsAndBaths/><Price/><Alert/></div></div>
)
}
As I said, only the MapContainer component is triggering the deactivation of the menu.
You can see the actual page at royaremlak.com/search

How to create button like this UI?

I am trying to create this button in react.js but can not do this.
My problem is not a CSS is that how to hide and display this button like UI.
This is the button before click:
And this is button after click :
My question is about how to create this toggle button that click on it invisible and show pic 2?
this is my code:
import React, {Component} from "react";
import axios from "axios";
import ContentUploadForm from "../../../dashboardContent/ContentUploadForm";
class UploadContentButton extends Component {
constructor(props) {
super(props);
this.state = {
file : null
};
this.onFormSubmit = this.onFormSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
onFormSubmit (e) {
e.preventDefault();
const formData = new FormData();
formData.append('filename',this.state.file);
const config = {
headers : {
'content-type' : 'multipart/form-data'
}
};
axios.post("/api/momayezi/uploadFiles/upload" , formData , config)
.then((response) => {
alert("The file is successfully uploaded");
}).catch((error) => {
console.log(error)
})
}
onChange (e) {
this.setState({
file : e.target.files[0]
});
}
render() {
return (
<div className="mt-5">
<div className={"row"}>
<div className={"col-12"}>
<form onSubmit={this.onFormSubmit}>
<input accept={"jpg"} type={"file"} name={"filename"} onChange={this.onChange}/>
<button type={"submit"}>ارسال</button>
</form>
<ContentUploadForm />
</div>
</div>
</div>
);
}
}
export default UploadContentButton
You can have one state variable to toggle the screens.
const Component = () => {
const [showForm, setShowForm] = React.useState(false);
return (
<div>
{showForm ? (
<div>
<div onClick={() => setShowForm(false)}> ← go back </div>
<div className="second"> Form Here </div>
</div>
) : (
<div>
<button className="first" onClick={() => setShowForm(true)}> Click me </button>
</div>
)}
</div>
);
};
ReactDOM.render(<Component />, document.getElementById("app"))
.first {
width: 400px;
border-radius: 10px;
border: 1px solid grey;
}
.second {
width: 400px;
height: 200px;
margin-top: 20px;
border: 1px solid grey;
}
<script crossorigin src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Full screen drag and drop files in React

In this official example of react-dropzone, a full screen drop zone is achieved by wrapping the whole app inside the <Dropzone /> component. I am creating a multi route app and feel that wrapping everything inside the <Dropzone /> component is not a very clean solution.
Is there a way to create a full screen/page drop zone in React without placing the <Dropzone /> component on the root level?
Create a route to a Dropzone form and adjust the height and size of the field by utilizing CSS.
Working example: https://codesandbox.io/s/l77212orwz (this example uses Redux Form, but you don't have to)
container/UploadForm.js
import React, { Component } from "react";
import { reduxForm } from "redux-form";
import ShowForm from "../components/showForm";
class UploadImageForm extends Component {
state = { imageFile: [] };
handleFormSubmit = formProps => {
const fd = new FormData();
fd.append("imageFile", formProps.imageToUpload[0]);
// append any additional Redux form fields
// create an AJAX request here with the created formData
};
handleOnDrop = newImageFile => this.setState({ imageFile: newImageFile });
resetForm = () => {
this.setState({ imageFile: [] });
this.props.reset();
};
render = () => (
<div style={{ padding: 10 }}>
<ShowForm
handleOnDrop={this.handleOnDrop}
resetForm={this.resetForm}
handleFormSubmit={this.handleFormSubmit}
{...this.props}
{...this.state}
/>
</div>
);
}
export default reduxForm({ form: "UploadImageForm" })(UploadImageForm);
components/showForm.js
import isEmpty from "lodash/isEmpty";
import React from "react";
import { Form, Field } from "redux-form";
import DropZoneField from "./dropzoneField";
const imageIsRequired = value => (isEmpty(value) ? "Required" : undefined);
export default ({
handleFormSubmit,
handleOnDrop,
handleSubmit,
imageFile,
pristine,
resetForm,
submitting
}) => (
<Form onSubmit={handleSubmit(handleFormSubmit)}>
<Field
name="imageToUpload"
component={DropZoneField}
type="file"
imagefile={imageFile}
handleOnDrop={handleOnDrop}
validate={[imageIsRequired]}
/>
<button
type="submit"
className="uk-button uk-button-primary uk-button-large"
disabled={submitting}
>
Submit
</button>
<button
type="button"
className="uk-button uk-button-default uk-button-large"
disabled={pristine || submitting}
onClick={resetForm}
style={{ float: "right" }}
>
Clear
</button>
</Form>
);
components/dropzoneField.js
import React, { Fragment } from "react";
import DropZone from "react-dropzone";
import { MdCloudUpload } from "react-icons/md";
import RenderImagePreview from "./renderImagePreview";
export default ({
handleOnDrop,
input,
imagefile,
meta: { error, touched }
}) => (
<div>
<DropZone
accept="image/jpeg, image/png, image/gif, image/bmp"
className="upload-container"
onDrop={handleOnDrop}
onChange={file => input.onChange(file)}
>
<div className="dropzone-container">
<div className="dropzone-area">
{imagefile && imagefile.length > 0 ? (
<RenderImagePreview imagefile={imagefile} />
) : (
<Fragment>
<MdCloudUpload style={{ fontSize: 100, marginBottom: 0 }} />
<p>Click or drag image file to this area to upload.</p>
</Fragment>
)}
</div>
</div>
</DropZone>
{touched && error && <div style={{ color: "red" }}>{error}</div>}
</div>
);
components/renderImagePreview.js
import map from "lodash/map";
import React from "react";
export default ({ imagefile }) =>
map(imagefile, ({ name, preview, size }) => (
<ul key={name}>
<li>
<img src={preview} alt={name} />
</li>
<li style={{ textAlign: "center" }} key="imageDetails">
{name} - {size} bytes
</li>
</ul>
));
styles.css
.dropzone-container {
text-align: center;
background-color: #efebeb;
height: 100%;
width: 100%;
}
.dropzone-area {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.upload-container {
height: 100vh;
width: 100%;
margin-bottom: 10px;
}
ul {
list-style-type: none;
}
p {
margin-top: 0;
}

How to reset button's value to click in react

Given the following code I am struggling to figure out how to set value of button back to original state, after it is clicked once ?
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
/**
* links : https://www.youtube.com/watch?v=GhbhD1HR5vk&t=297s
* https://reactjs.org/docs/handling-events.html
*
*
*
*/
class Input extends Component {
constructor(props) {
super(props);
this.state = {
tagged: false,
user: '',
tag: ''
}
this.handleUserChange = this.handleUserChange.bind(this);
}
handleClick(e) {
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
handleUserChange(e) {
console.log("e.target.value");
this.setState({user: e.target.value});
}
handleTagChange(e) {
console.log(e.target.value);
this.setState({tag: e.target.value});
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text"
onChange={ this.handleUserChange.bind(this) }
>
</input>
<input
style = {textStyle}
placeholder="tag"
type="text"
onChange={ (e) => this.handleTagChange(e) }
>
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? this.state.user + ' was tagged with ' + this.state.tag : ''}
{/* {this.setState({tagged: false})} */}
</p>
</div>
)
}
}
var divStyle = {
position: 'relative',
top:'50%',
left: '15%',
};
var textStyle = {
margin: '20px 20px 20px 20px',
height: '20px',
width: '200px',
};
var buttonStyle = {
margin: '20px 20px 20px 20px',
background: '#7FFFD4',
color: 'black',
height: '25px',
width: '250px'
};
export default Input;
set your state like this in your handClick method
this.setState((prevState)=> ({
tagged: !prevState.tagged
}));

Resources