Why div in a form is a problem for react? - reactjs

I have a following button which is connected to recaptcha according to docs
<Button
onClick={() => setShowSpinner(true)}
size="lg"
className="g-recaptcha"
data-sitekey="XYZ"
data-callback="handleFormSend"
data-action='submit'
>
{showSpinner && <Spinner
as="span"
animation="grow"
size="sm"
role="status"
aria-hidden="true"
/>}
Send
</Button>
I don't understand why in chrome I got
"Warning: Did not expect server HTML to contain a <div> in <form>."
Of course I checked HTML code and don't see any div? In Mozilla there is no warning.
I use next and react.
What may be wrong?

Looks like a SSR/hydration issue. Try removing spaces between tags.
<Button
onClick={() => setShowSpinner(true)}
size="lg"
className="g-recaptcha"
data-sitekey="XYZ"
data-callback="handleFormSend"
data-action='submit'
>
{showSpinner &&
<Spinner
as="span"
animation="grow"
size="sm"
role="status"
aria-hidden="true"
/>
}
Send
</Button>
Check this answer

Related

TypeError: Cannot set properties of undefined (setting 'hook')

TypeError: Cannot set properties of undefined (setting 'hook')
I am working on a Nextjs application but getting this error with antd library. I'm using the modal component and tooltip component which causes a re-render on open and close and spits out this error multiple times. Same goes for the tooltip when I mouse over it. Has anyone experienced this? and how did you fix it?. Answers appreciated!
import { Button, Modal, Tooltip } from 'antd';
const [isModalOpen, setIsModalOpen] = useState(false);
<div className="d-flex gap-2">
<Tooltip title="Edit">
<EditOutlined className="h5 pointer text-warning" />
</Tooltip>
<Tooltip title="Publish">
<CheckOutlined className="h5 pointer text-success ml-2" />
</Tooltip>
</div>
<Button
className="w-100"
onClick={() => setIsModalOpen(true)}
type="primary"
shape="round"
size="large"
icon={<UploadOutlined />}
>
Open modal
</Button>
<Modal
title="Modal title"
centered
open={isModalOpen}
onCancel={() => setIsModalOpen(false)}
footer={null}
>
<p>Some contents...</p>
</Modal>

Field Array in React using formik

I wanted to follow like a todo list. Something just like in the picture below.
Right now, the problem with my code is that, its working differently.
I wanted only one input that renders a list of divs instead of input fields.
Exactly just like in the picture below:
Pls check my codesandbox here
CLICK HERE
<FieldArray
name="todos"
render={(arrayHelpers) => (
<div>
{formik.values.todos.map((friend, index) => (
<div key={index} style={{ display: "flex", gap: "1rem" }}>
<input
name={`todos[${index}].name`}
value={formik.values.todos[index].name}
onChange={formik.handleChange}
/>
<button
disabled={formik.values.todos?.length === 1}
type="button"
onClick={() => arrayHelpers.remove(index)}
className="deleteButton"
>
Remove
</button>
</div>
))}
<button
type="button"
onClick={() => arrayHelpers.push({ name: "" })}
>
Add
</button>
</div>
)}
/>
Here is a very simple and rude approach - I used Formik my project some time ago and I'm pretty sure it's not perfect but this is exactly what you need.
So some details.
do not render input for every item in your list, you need only render it's value and element with delete handler
you need only one controlled input and it's value is used for name field in your todos. State is cleaned when you click Add button.
you need to render your element only if formik.values.todos.lenght > 0
you need to disable Delete button when formik.values.todos.lenght === 1
Add button should be disabled when newValue.lenght === 0
Piece a cake, right?

Autoclose bootstrap 5 Dropdown without toggle in React

I have a search field that shows data as dropdown.item when user is typing. The library is React Bootstrap (bootstrap 5). This is working great. The dropdown is showing. The problem is that the dropdown persist when clicking outside or navigating to a new link. The dropdown is in a header that does not get rerendered with the rest of the page. Using NextJS. Any tips on how to close a dropdown that has no toggle?
<form className="d-none d-sm-inline-block" style={{ zIndex: "1000" }}>
<div className="input-group input-group-navbar">
<input
type="text"
className="form-control"
placeholder="Søk"
aria-label="Search"
onChange={(event) => {
setSearchTerm(event.target.value);
}}
/>
<button className="btn" type="button">
<Icon.Search className="align-middle" />
</button>
</div>
{searchData.length >= 1 && (
<Dropdown style={{ position: "absolute", background: "white" }} autoClose="outside">
{searchData.slice(0, 10).map((element, index) => {
return (
<Link key={element.agressoResourceId} href={`employees/69918`} passHref replace={true}>
<Dropdown.Item>
{element.firstname} - {element.lastname}
</Dropdown.Item>
</Link>
);
})}
</Dropdown>
)}
</form>
The solution was to use onBlur event and hide the dropdown. The problem comes with the onblure is triggered before you press the item. The solution here was to use a setTimeout of 200ms.

Close React-Bootstrap Popover with a button that's inside popover

I'm using React-Bootstrap Popover. I would like the popover to close once a user clicks on a close button located inside the popover. I would prefer a solution that doesn't use refs as facebook doesn't recommend using them. Here is my code
const popoverTop = (
<Popover id="popover-positioned-top" title="Popover top">
<button type="button" className="close">×</button>
<strong>Holy guacamole!</strong> Check this info.
</Popover>
);
<OverlayTrigger trigger="click" placement="top" overlay={popoverTop}>
<Button>Holy guacamole!</Button>
</OverlayTrigger>
Here is what helped me :
<OverlayTrigger
container={this}
trigger="click"
placement="right"
overlay={this.popoverClick}
rootClose={true}
>
<Button aria-label="Get Info" bsSize="medium">
Button Name
</Button>
</OverlayTrigger>
where popoverClick is:
<Popover id="popover-positioned-scrolling-right" className="popover-main">
<div className="popover-custom-header">
<h3 className="popover-title">Your Title</h3>
<IconButton aria-label="Close" className="icon-button"
onClick={() => document.body.click()}>
<Close fontSize="small"/>
</IconButton>
</div>
<div class="popover-custom-content">
{/* ... the content you need */}
</div>
</Popover>
document.body.click() -> does all the work.
Ref: https://stackoverflow.com/a/47636953/9743227
I hope it will help you, too!
I know that a lot of time has passed, today I had this same problem and I arrived here. I found a way to fix it.
<OverlayTrigger trigger = 'your-trigger' placement = 'auto' rootClose
ref = 'overlay'>
<Popover title='' >
------
</Popover>
<Button onClick={ this.hidePopover } ></Button>
</OverlayTrigger>
then in the method
hidePopover = ( ) =>
{
this.refs.overlay.handleHide();
}
I hope I have helped

reactJS material UI Icon button to upload file

I want to know how can I open the directory to upload a file using an IconButton?
<IconButton
iconClassName="fa fa-plus-square"
onClick={(e) => e.stopPropagation()}
type='file'
/>
using the code below shows the icon button and another button for the upload file
<IconButton iconClassName="fa fa-plus-square" onClick={(e) => e.stopPropagation()}>
<input type="file type='file'>
</IconButton>
I think the standard way from material ui examples:
<input accept="image/*" className={classes.input} id="icon-button-file" type="file" />
<label htmlFor="icon-button-file">
<IconButton color="primary" className={classes.button} component="span">
<PhotoCamera />
</IconButton>
</label>
A few things:
You don't need type='file' on the IconButton, just on the input
IconButton does not expect its children to be anything other than an SVGIcon, so I recommend that you use a regular button
I wouldn't call stopPropagation in this case
You have a typo in your type prop for the input. You have type="file type='file'. It should just be type="file"
So, putting that all together:
<FlatButton label="Choose file" labelPosition="before">
<input type="file" style={styles.exampleImageInput} />
</FlatButton>
If you still want it to be an icon rather than a button, I suspect you can do something with <input> or add it as the children to FlatButton with no label.
You can achieve the same with IconButton using the following code:
<IconButton onClick={() => this.fileUpload.click()}>
<FontIcon className="material-icons" >
add_a_photo
</FontIcon>
</IconButton>
<input type="file" ref={(fileUpload) => {
this.fileUpload = fileUpload;
}}
style={{ visibility: 'hidden'}} onChange={this.groupImgUpload} />

Resources