Discordance between component state and its props - reactjs

I am making a basic drag and drop utility where you can drag and recombine the position of three cards in React.
I dont know why but there seems to be discordance between the actual data on the parents state and its child. After some refactoring following users input, things are as this:
onDrop = (event) => {
event.preventDefault();
event.stopPropagation();
const newData = this.props.getDraggedCard(); //gets the data actually being dragged around
let receiverCard = Object.assign({}, this.state) //backup of the previous state
this.setState({
_id: newData._id,
text: newData.text,
title: newData.title,
subtitle: newData.subtitle,
image: newData.image
}, () => { this.props.onDropParentData(receiverCard) })
}
this function is on every child component, which are the items actually to be moved around.
The parent component, which stores and saves the data:
onDropParentData = (receiverCard) => {
let {slideInformation}=this.state; //the state where all the data is
let draggedCard = this.state.draggedCard; //the data being dragged
const indexDragged= slideInformation.findIndex((element)=>element.id===draggedCard.id)
const indexReceiver= slideInformation.findIndex((element)=>element.id===receiverCard.id)
let draggedCardIdStorage = this.state.draggedCard.id;
draggedCard.id = receiverCard.id;
receiverCard.id = draggedCardIdStorage;
slideInformation.splice(indexDragged,1,draggedCard);
slideInformation.splice(indexReceiver,1,receiverCard);
this.setState({slideInformation});
}
with this actual code, the state holds the correct information but when dragging and dropping, items dont switch between positions as desired, only the dropped item gets its new position.
The render method on the parent is:
{this.state.slideInformation.map((slide,index) => {
return (
<CardFormBody
getDraggedCard={this.getDraggedCard}
key={index}
onDropParentData={this.onDropParentData}
onDrag={this.onDrag}
slide={slide}
onDragOver={this.onDragOver}
setFormData={this.setFormData}
/>
)
})}
And every CardFormBody is
<div draggable onDrag={(event) => { this.props.onDrag(event, this.state) }} className="newsCard" name={this.state.id}>
<label>Título</label>
<input name={this.state.id} onChange={this.handleTitleChange} value={this.props.slide.title} />
<label>Subtítulo</label>
<input name={this.state.id} onChange={this.handleSubtitleChange} value={this.state.subtitle} />
<label>Texto</label>
<textarea onDragOver={this.props.onDragOver} onDrop={this.onDrop} name={this.state.id} onChange={this.handleTextChange} value={this.state.text} />
<button type="button" name={this.state.id} onClick={this.handleImgChange}>Añadir Imagen</button>
<div className="imageWrapperForm">
<img alt="preview" name={this.state.id} className="previewImg" src={this.state.image} />
</div>
</div>

Ciao, can you provide more code? How you pass data from child to parent? Anyway I think the misalignment between children and parent data could be on how you pass them.

Related

useState resets to init state in CRUD function when edit - ReactStars Component

I'm trying to make a CRUD person function where each person has an array of skills.
I want a function where you're able to add/edit/remove skills on a given person.
Each array consist of a skill element as a string and a star element as an integer. I've made some dynamic inputfields with an add and a remove function for more/less inputfields in a bootstrap modal.
The data is fetched from Firebase with a useEffect and set as setData in EditPerson.jsx. No problem here.
The issue consist of 3 components atm: EditPerson -> ModalEditSkills -> EditSkills. (Please let me know if this is a bad structure).
I'm now able to set the useState of newData in SkillEdit.jsx with the correct data. This makes sure that on EditPerson I'll be able to view the correct data input from given in the EditSkills. Also if I console.log the data in EditSkills I can see that it works like a charm. But when I close the bootstrap modal and open it again the useState in index 0 have been reset to init useState (0).
I can't add images in the text here yet, so here's some links for the images if needed.
The image explains that the console.log tells me that the useState is set correct, but it stills reset the state of index 0 everytime I re-open the modal.
Hope that makes sense otherwise let me know.
ReactStars-choosen
Console.log
EditPerson.jsx
const EditPerson = () => {
const [data, setData] = useState({});
const [skills, setSkills] = useState([]);
const { id } = useParams();
useEffect(() => {
if (id) {
const fetchData = async () => {
const docRef = doc(db, "person", id);
try {
const docSnap = await getDoc(docRef);
setData(docSnap.data());
} catch (error) {
console.log(error);
}
};
fetchData().catch(console.error);
} else {
setData("");
}
}, [id]);
useEffect(() => {
if (data) {
setSkills(data.skills);
}
}, [data]);
const handleSkills = (skill) => {
setSkills(skill);
};
return (
<div>
<ModalEditSkills
handleSkills={handleSkills}
data={skills}
/>
</div>
);
}
ModalEditSkills.jsx
const ModalEditSkills = ({ data, handleSkills }) => {
const [show, setShow] = useState(false);
const [newData, setNewData] = useState({});
useEffect(() => {
if (data) {
setNewData(data);
}
}, [data]);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const handleSubmitSkills = (e) => {
e.preventDefault();
handleSkills(newData);
setShow(false);
};
return (
<>
<div className="content_header">
<div className="content_header_top">
<div className="header_left">Skills</div>
<div className="header_right">
<Button className="round-btn" onClick={handleShow}>
<i className="fa-solid fa-pencil t-14"></i>
</Button>
</div>
</div>
</div>
<Modal show={show} onHide={handleClose} size="">
<Modal.Header closeButton>
<Modal.Title>Edit Person</Modal.Title>
</Modal.Header>
<Modal.Body>
<SkillEdit data={data} setNewData={setNewData} />
</Modal.Body>
<Modal.Footer>
<Form>
<Button className="btn-skill-complete" onClick={handleSubmitSkills}>
Save
</Button>
</Form>
</Modal.Footer>
</Modal>
</>
);
};
SkillEdit.jsx
const SkillEdit = ({ data, setNewData }) => {
const [inputField, setInputField] = useState([{ skill: "", stars: 0 }]);
const handleAddFields = () => {
setInputField([...inputField, { skill: "", stars: 0 }]);
};
const handleRemoveFields = (index) => {
const values = [...inputField];
values.splice(index, 1);
setInputField(values);
setNewData(values);
};
const handleChangeInput = (index, name, value) => {
const values = [...inputField];
values[index][name] = value;
setInputField(values);
setNewData(values);
};
useEffect(() => {
if (data) {
const setSkills = () => {
setInputField(data);
};
setSkills();
}
}, [data]);
return (
<Form>
<div>
{inputField?.map((inputField, index) => (
<div key={index}>
<Row>
<Col xs={5} md={5}>
<Form.Group as={Col}>
<Form.Control
className="mb-3"
type="text"
id="skill"
name="skill"
value={inputField?.skill}
onChange={(event) =>
handleChangeInput(index, "skill", event.target.value)
}
/>
</Form.Group>
</Col>
<Col xs={4} md={4}>
<div>
<Form.Group>
<ReactStars
type="number"
name="stars"
count={5}
size={24}
id="stars"
onChange={(newValue) =>
handleChangeInput(index, "stars", newValue)
}
emptyIcon={<i className="fa-solid fa-star"></i>}
filledIcon={<i className="fa-solid fa-star"></i>}
value={inputField.stars}
/>
</Form.Group>
</div>
</Col>
<Col xs={3} md={3}>
<div>
<button
type="button"
onClick={() => handleAddFields()}
>
<i className="fa-solid fa-plus"></i>
</button>
<button
type="button"
onClick={() => handleRemoveFields(index)}
>
<i className="fa-solid fa-minus"></i>
</button>
</div>
</Col>
</Row>
</div>
))}
</div>
</Form>
);
};
This took some time for me to work out. I had trouble reproducing and still do, but I noticed a lot of odd behaviour around the stars. In the end, I've figured out its probably this bug in the react-stars package.
Unfortunately, the value prop does not actually control the value after the initial render. So It's like an uncontrolled component. The library therefore, is poor. It hasn't been committed to for 4 years. Usually, if a component is uncontrolled, the developer calls the prop initialValue or defaultValue instead of value, which usually implies the component is controlled. Here, the author has made a mistake. Regardless, in your case, you need controlled mode.
It's possible theres another bug interacting. But I'd start by replacing react-stars as not being able to have controlled mode is extremely poor and it makes it very hard to see the wood through the trees. There is a "solution" in the github thread but its a massive hack -- its using the special key property to remount it every time the value changes.
I went looking for an alternative and much to my surprise a lot of the other libraries are also uncontrolled -- which really sucks. What you could do instead of the hack in the github issue, is make it so the dialog is unmounted when open is false. This would mean each time the dialog opens it resets the value back to that which is held in the parent state. See my bottom code for that solution.
There's good options though here and here but they are part of larger design systems, and its probably overkill to bring in a whole other design system when you have committed to bootstrap. Depending on how early you are in your project though, I'd seriously consider switching to something like MUI. Personal opinion territory, but bootstrap is pretty outdated and the React wrapper and associated community, plus diversity of components, is much smaller. It shows that react-bootstrap is a wrapper on top of old school global CSS files as opposed to material-ui which was built from the ground up in React and has a React based CSS-in-JS solution. When people first start learning react, they often slip into bootstrap because its what they know from non-react dev -- but using a framework like React moves the needle and trade offs.
It's not your problem here, but I feel the need to say it :D. At the same time I'd say don't always take a random internet strangers recommendation and refactor for nothing -- you should research it.
A few other important notes:
If id is not set, you set data to an empty string. If that case ever happened for real, your code would error since accessing data.skills would result in undefined. I would argue that you shouldn't even need to handle this case, since your router setup should be such that there is no mapping between this component and a route without an id. Make sure on your router config the id param is non-optional.
You are copying data.skills into a new state item called skills. It's not a bug per-se but it is a code smell as its not actually necessary. Why not edit the data in the data state directly? Copying state that is fundamentally the same is usually an anti-pattern as you can fall into traps where you are trying to keep 2 bits of state in sync that are supposed to be the same. I think its ok where you do it further down as I believe you are copying it because you want that state not to be committed further up until the user clicks save -- which means its actually fundamentally different state at given times. But that doesnt apply to the top level data vs skills one. Actually, I think the inputField state is also not needed since your "staged" state is held by the parent ModalEditSkills in newData. You could instead get rid of this inputField state and have handleChangeInput, handleAddFields and handleRemoveFields call up into ModalEditSkills to patch newData directly. Then pass that down. This will greatly reduce the surface area for bugs and remove unnecessary effects in SkillEdit.
You are often passing props called set[Something]. Generally, in react, you want to keep to the naming convention of user triggered events beginning with on. The trouble with the former, is it implies that the user action does a certain thing, which makes the component look like its less reusable in other contexts (even though its the same behaviour really, its just incorrect naming).
When setting a state item thats derived partly from its previous value, you should use the callback pattern of setState (which is passed the current value) instead of referencing the state value returned from useState. This avoids bugs to do with accidentally getting a stale value when you update state in a loop or something. React doesn't actually update the value of the state immediately, it gets flushed at the end of the call stack. Using the previous value callback gets around this. Not a problem that will show up in your code, just good practice that you should get in the habit of.
There's a bug where you need to reset the form data back to the data stored in the top component when it opens/closes because currently if you make a change and close dialogue, without clicking save, its still there next time you open it. Its not actually saved to the parent state, its just hanging around in the background (hidden). Its weird UX so I've fixed by adding show to the effect that resets the newData state. If you really wanted it how it was though you can just remove that again from the deps array.
There was also a bug in the way you were patching the state when editing an existing skill. Even though you cloned the skills array by spreading a new one, this only does a shallow clone. The object you spread into the array are the same (as in literally, the same object reference) as the original ones. This meant you were mutating the data prop which is not allowed in react. I've changed to Object.assign to make sure its a proper edited clone. The way this works if everything gets merged from right to left. So by the first param being {}, you start with a brand new object and then you load int the old + new data into it. Libraries like Immer make this easier, you might want to look into it.
I haven't fixed this one as it's kind of up to you but if you were on slow network, there would be a period where you could confuse the user since the data hasn't come back yet but they can open the dialogue and see no skills. You might want to handle that case by showing a loading display instead of the rest of the app whilst its in flight. You could make the default state of the top level data state null and then only populate it when the request comes back like you do now. Then in the top level render you'd check for null and return some loading display instead of ModalEditSkills. Similar stuff would happen if the network errored. You might also want to have some new state that says if an error happened (instead of just logging), and check that as well and display the error page.
Heres the code with my proposed changes (minus the library change, you'd still need to do that if you cared enough).
And heres a code sandbox with it working: https://codesandbox.io/s/wispy-meadow-3ru2nq?file=/src/App.js (I replaced the network call with static data for testing, and I dont have your icons).
I hope this feedback helps you on your react journey!
const EditPerson = () => {
const [data, setData] = useState({skills: []});
const { id } = useParams();
useEffect(() => {
const fetchData = async () => {
const docRef = doc(db, "person", id);
try {
const docSnap = await getDoc(docRef);
setData(docSnap.data());
} catch (error) {
console.log(error);
}
};
fetchData().catch(console.error);
}, []);
const handleSkillsChanged = (skills) => {
setData(data => ({...data, skills}));
}
return (
<div>
<ModalEditSkills
onSkillsChanged={handleSkillsChanged}
data={data.skills}
/>
</div>
);
}
const ModalEditSkills = ({ data, onSkillsChanged}) => {
const [show, setShow] = useState(false);
const [newData, setNewData] = useState([]);
useEffect(() => {
setNewData(data);
}, [data, show]);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const handleSkillChange = (index, name, value) => {
setNewData(prevValues => {
const newValues = [...prevValues]
newValues[index] = Object.assign({}, newValues[index], { [name]: value });
return newValues
});
}
const handleSkillAdded = () => {
setNewData(prevValues => [...prevValues, { skill: "", stars: 0 }]);
}
const handleSkillRemoved = (index) => {
setNewData(prevValues => {
const newValues = [...prevValues];
newValues.splice(index, 1);
return newValues
});
}
const handleSubmitSkills = (e) => {
e.preventDefault();
onSkillsChanged(newData);
setShow(false);
};
return (
<>
<div className="content_header">
<div className="content_header_top">
<div className="header_left">Skills</div>
<div className="header_right">
<Button className="round-btn" onClick={handleShow}>
<i className="fa-solid fa-pencil t-14"></i>
</Button>
</div>
</div>
</div>
{show && (
<Modal show={show} onHide={handleClose} size="">
<Modal.Header closeButton>
<Modal.Title>Edit Person</Modal.Title>
</Modal.Header>
<Modal.Body>
<SkillEdit
data={newData}
onSkillChanged={handleSkillChange}
onSkillAdded={handleSkillAdded}
onSkillRemoved={handleSkillRemoved}
/>
</Modal.Body>
<Modal.Footer>
<Form>
<Button
className="btn-skill-complete"
onClick={handleSubmitSkills}
>
Save
</Button>
</Form>
</Modal.Footer>
</Modal>
)}
</>
);
};
const SkillEdit = ({ data, onSkillChanged, onSkillRemoved, onSkillAdded}) => {
return (
<Form>
<div>
{data?.map((inputField, index) => (
<div key={index}>
<Row>
<Col xs={5} md={5}>
<Form.Group as={Col}>
<Form.Control
className="mb-3"
type="text"
id="skill"
name="skill"
value={inputField?.skill}
onChange={(event) =>
onSkillChanged(index, "skill", event.target.value)
}
/>
</Form.Group>
</Col>
<Col xs={4} md={4}>
<div>
<Form.Group>
<ReactStars
type="number"
name="stars"
count={5}
size={24}
id="stars"
onChange={(newValue) =>
onSkillChanged(index, "stars", newValue)
}}
emptyIcon={<i className="fa-solid fa-star"></i>}
filledIcon={<i className="fa-solid fa-star"></i>}
value={inputField.stars}
/>
</Form.Group>
</div>
</Col>
<Col xs={3} md={3}>
<div>
<button
type="button"
onClick={onSkillAdded}
>
<i className="fa-solid fa-plus"></i>
</button>
<button
type="button"
onClick={() => onSkillRemoved(index)}
>
<i className="fa-solid fa-minus"></i>
</button>
</div>
</Col>
</Row>
</div>
))}
</div>
</Form>
);
};

Trying to add multiple refs to dynamically generated element in ReactJs

I am trying to add multiple refs to a set of dynamically generated checkboxes. At this point, the checkboxes work, but when I am trying to change the checked state of a particular checkbox, it seems the last one is the only one to have the ref and the state updates just for that particular checkbox.
So far I have this:
// Setting 6 as a number of states
new Array(states.length).fill(false)
);
// Adding refs to check values
const inputsRef = useRef([]);
const handleStateChecked = (position) => {
const updateCheckedState = isStateChecked.map((isChecked, index) =>
index === position ? !isChecked : isChecked
);
setStateIsChecked((prevState) => updateCheckedState);
};
return (
{ ... form ...}
{/* Generating state checkboxes dynamically */}
{states.map((state, index) => {
return (
{...div with styles}
<input
type="checkbox"
checked={isStateChecked[index]}
onChange={ () => handleStateChecked(index)}
value={state}
ref={inputsRef}
/>
{state}
</div>
);
})}
</div>
</div>
Could someone guide me in the right direction? Thanks!

how can I remove part of data from state in react.js

I create and add some data to my selecetFile2 state / then I want to delete some part of that selecetFile2 state by any event- just guide for function.
const [selectedFile2, setSelectedFile2] = useState([]); //my state for data
const [isFilePicked2, setIsFilePicked2] = useState(false); //just controll for page
this function for control data
const changeHandler2 = (event) => {
setSelectedFile2([...selectedFile2,event.target.files[0]]);
setIsFilePicked(true);}
const multi_img = ()=>{ //It's for input dialog box
document.getElementById("multi_img").click();}
this my main code
<input type="file" onChange={changeHandler2} title="ali ali" id="multi_img"
name="img" accept="image/*" style={{display:'none'}} />
<div><BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map(item => <img key={v4()} src={URL.createObjectURL(item)} />)
//this my Item I want to delete for example by click
//I just need function
}
Here you go
<input
type="file"
onChange={changeHandler2}
title="ali ali"
id="multi_img"
name="img"
accept="image/*"
style={{ display: "none" }}
/>
<div>
<BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map((item) => (
<img key={v4()} src={URL.createObjectURL(item)} onClick={ () => {
setSelectedFile2(selectedFile2.filter(i => i !== item))
}} />
))
//this my Item I want to delete for example by click
//I just need function
}
</div>
By using useState, you can not directly update or modify the state. Whenever you wanted to modify or update the state you have to do it using the set[nameofstate]. In your case.
whenever you want to update selectedFile2 you have to pass the new value for seletedFile2 to setSelectedFile2(newValueForSelectedFile2).
for more information and examples please visit documenation

Accessing a component state from a sibling button

I'm building a page that will render a dynamic number of expandable rows based on data from a query.
Each expandable row contains a grid as well as a button which should add a new row to said grid.
The button needs to access and update the state of the grid.
My problem is that I don't see any way to do this from the onClick handler of a button.
Additionally, you'll see the ExpandableRow component is cloning the children (button and grid) defined in SomePage, which further complicates my issue.
Can anyone suggest a workaround that might help me accomplish my goal?
const SomePage = (props) => {
return (
<>
<MyPageComponent>
<ExpandableRowsComponent>
<button onClick={(e) => { /* Need to access MyGrid state */ }} />
Add Row
</button>
<MyGrid>
<GridColumn field="somefield" />
</MyGrid>
</ExpandableRowsComponent>
</MyPageComponent>
</>
);
};
const ExpandableRowsComponent = (props) => {
const data = [{ id: 1 }, { id: 2 }, { id: 3 }];
return (
<>
{data.map((dataItem) => (
<ExpandableRow id={dataItem.id} />
))}
</>
);
};
const ExpandableRow = (props) => {
const [expanded, setExpanded] = useState(false);
return (
<div className="row-item">
<div className="row-item-header">
<img
className="collapse-icon"
onClick={() => setExpanded(!expanded)}
/>
</div>
{expanded && (
<div className="row-item-content">
{React.Children.map(props.children, (child => cloneElement(child, { id: props.id })))}
</div>
)}
</div>
);
};
There are two main ways to achieve this
Hoist the state to common ancestors
Using ref (sibling communication based on this tweet)
const SomePage = (props) => {
const ref = useRef({})
return (
<>
<MyPageComponent>
<ExpandableRowsComponent>
<button onClick={(e) => { console.log(ref.current.state) }} />
Add Row
</button>
<MyGrid ref={ref}>
<GridColumn field="somefield" />
</MyGrid>
</ExpandableRowsComponent>
</MyPageComponent>
</>
);
};
Steps required for seconds step if you want to not only access state but also update state
You must define a forwardRef component
Update ref in useEffect or pass your API object via useImerativeHandle
You can also use or get inspired by react-aptor.
⭐ If you are only concerned about the UI part (the placement of button element)
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
(Mentioned point by #Sanira Nimantha)

How to initialize a StandaloneSearchBox component with a given address?

I have a react component for a google.maps.places.SearchBox without the map, which is a StandaloneSearchBox. I want to pass it props with the initial value (which is only the formated version of the address, e.g "London, Kentucky, États-Unis") and then be able to change the address in the input field.
I have a places property in the state, which I want to hold the place object. How can I pass in the beginning in the componentDidMount() method the initial value so I can set it to the places object? It doesn't work in this way.
const PlacesWithStandaloneSearchBox = compose(
withProps({
googleMapURL: googleMapsURI,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />
}),
lifecycle({
componentWillMount() {
console.log("componentWillMount");
const refs = {};
this.setState({
places: [],
onSearchBoxMounted: ref => {
refs.searchBox = ref;
},
onPlacesChanged: () => {
const places = refs.searchBox.getPlaces();
this.setState({
places
});
}
})
},
componentDidMount() {
this.setState({
places: this.props.value
});
}
}),
withScriptjs
)(props =>
<div className="fretlink-input form-group" data-standalone-searchbox="">
<StandaloneSearchBox
ref={ props.onSearchBoxMounted }
bounds={ props.bounds }
onPlacesChanged={ props.onPlacesChanged }>
<input
className="form-control"
placeholder={ props.placeholder }
type="text" />
</StandaloneSearchBox>
<ol>
{ props.places.map(({ place_id, formatted_address, geometry: { location } }) =>
<li key={ place_id }>
{ formatted_address }
{" at "}
({location.lat()}, {location.lng()})
</li>
)}
</ol>
</div>
);
export default PlacesWithStandaloneSearchBox;
It appears that initializing the StandaloneSearchBox with an actual Google Maps place object, based on a search on address text or lat lng, isn't possible out of the box with a component prop or otherwise.
I think the best you can do is implement this yourself, by manually doing a search with the Google Maps places API with whatever data you have, getting that initial place, and setting it via this.setState in componentDidMount as in your example.
However, I didn't do this, because I found a solution to this that's a lot simpler, and I think will also apply in your case.
If you have the formatted address, there may actually be no reason to perform the search and populate the component with a full Google Maps place at all. All you really need is that text showing in the input. When you search for a new address, sure, you need all the data (lat lng etc) -- but that is already working. For the initial address, you probably already have this data. It's really just what you show in the <input> that's your concern.
Fortunately, it's really easy to separate the behaviour of the <input> from the behaviour of the StandaloneSearchBox because the <input> is just a child component that you can fully control.
What I did was just to use some more component state to hold the text that the input should show, and then make it a controlled component. Everything else works in exactly the same way, it's just that I take control of the 'view' which is the text displayed in the <input>.
Here is a rough example of what I mean, using your code:
// init the state with your initial value "1 Something Street, etc"
const [text, setText] = useState(INITIAL_VALUE_HERE)
<StandaloneSearchBox
ref={ props.onSearchBoxMounted }
bounds={ props.bounds }
// have onPlacesChanged set the state when a new option is picked
// to whatever the address text of the selected place is
// (needs to be implemented appropriately in onPlacesChanged of course)
onPlacesChanged={() => { props.onPlacesChanged(setText) }}
>
<input
className="form-control"
placeholder={ props.placeholder }
type="text"
value={text} // control the input value with state
onChange={(e) => { setText(e.target.value) }} // update the state when you type something
/>
</StandaloneSearchBox>
You can check my answer here: Initialize React Google Maps StandaloneSearchBox with geocode
In general you can't use address as a filter for SearchBox results, but you can specify the area in which to search for places:
<StandaloneSearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
onPlacesChanged={props.onPlacesChanged}
defaultBounds={new google.maps.LatLngBounds(
new google.maps.LatLng(40.712216, -74.22655),
new google.maps.LatLng(40.773941, -74.12544)
)}

Resources