Skip to content

Commit

Permalink
fix: checkboxes and radios being updated every two clicks (#273)
Browse files Browse the repository at this point in the history
* checkboxes are now updated on every click no matter if it is connected
or not

* radios now have et radiogroup from reakit and therefore, work without
an onChange prop

Fixes #203

Signed-off-by: Paul-Xavier Ceccaldi <[email protected]>
  • Loading branch information
P1X3L authored Aug 12, 2019
1 parent e82ca68 commit 16afd5d
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/components/ConnectedField/doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ You can find additional props for each field component in [Fields](/fields/file-
/>
<ConnectedField name="profile" component={FileUpload} label="Profile pic" mb="xl" />
<ConnectedField
dateIcon={<Icon name="celebrate" size="sm" color="nude.600" />}
name="partyDate"
component={DateTimePicker}
label="Party date"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Field/doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ You can find additional props for each field component in [Fields](/fields/file-
<Field
name="swatch"
component={Toggle}
label="Disabled switch example"
label="Disabled swatch example"
disabled
checked={!!values.swatch}
onChange={handleChange}
Expand Down
26 changes: 12 additions & 14 deletions src/components/Field/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { forwardRef, Fragment, useRef } from 'react'
import React, { forwardRef, Fragment, useRef, useState } from 'react'
import {
array,
arrayOf,
Expand Down Expand Up @@ -62,6 +62,8 @@ export const Field = forwardRef(

const inputRef = useRef()

const [isCheckboxChecked, setIsCheckboxChecked] = useState(checked)

const baseType = getBaseType(type || Component.displayName)
const variant = getVariant({ connected, touched, warning, error })
const hintText = getHintText({ connected, touched, warning, error, hint })
Expand All @@ -74,26 +76,21 @@ export const Field = forwardRef(
const htmlFor = makeUnique(isRadio ? value : id || name)

const handleLabelClick = () => {
if (isCheckable) return
const input = inputRef.current
if (input) {
switch (Component.displayName) {
case 'InputRadio':
case 'RadioTab':
case 'Checkbox':
break
case 'MarkdownEditor':
input.simpleMde.codemirror.focus()
break
default:
input.focus()
}
Component.displayName === 'MarkdownEditor'
? input.simpleMde.codemirror.focus()
: input.focus()
}
}

const handleChecked = () => (baseType === 'checkbox' ? isCheckboxChecked : checked)

const field = (
<Component
autoFocus={autoFocus}
checked={checked}
checked={handleChecked()}
connected
disabled={disabled}
flexDirection={layout}
Expand All @@ -107,6 +104,7 @@ export const Field = forwardRef(
placeholder={placeholder}
ref={inputRef || ref}
required={required}
setIsCheckboxChecked={setIsCheckboxChecked}
size={size}
type={baseType}
value={value}
Expand All @@ -120,7 +118,7 @@ export const Field = forwardRef(
return (
<S.Field
checkableField={isCheckable}
checked={checked}
checked={handleChecked()}
fieldType={Component.type}
flexDirection={layout}
size={size}
Expand Down
23 changes: 20 additions & 3 deletions src/components/InputCheckbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,26 @@ import { FINAL_FORM_INPUT_TYPES } from '../../utils'
import * as S from './styles'

export const InputCheckbox = forwardRef(
({ Component = S.InputCheckbox, name, order, ...rest }, ref) => (
<Component id={name} name={name} order={order} ref={ref} {...rest} />
)
(
{ checked, Component = S.InputCheckbox, name, onChange, order, setIsCheckboxChecked, ...rest },
ref
) => {
const toggle = () => setIsCheckboxChecked(!checked)
const handleChange = e => onChange && onChange(e)

return (
<Component
checked={checked}
id={name}
name={name}
onChange={handleChange}
onClick={toggle}
order={order}
ref={ref}
{...rest}
/>
)
}
)

InputCheckbox.type = 'InputCheckbox'
Expand Down
13 changes: 7 additions & 6 deletions src/components/InputRadio/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { forwardRef } from 'react'
import { bool, elementType, func, number, string } from 'prop-types'
import { useRadioState } from 'reakit/Radio'
import { bool, elementType, func, number, object, string } from 'prop-types'

import * as S from './styles'

export const InputRadio = forwardRef(({ name, order, value, ...rest }, ref) => {
const radio = useRadioState()
return (
export const InputRadio = forwardRef(
({ name, order, radio, setIsCheckboxChecked, value, ...rest }, ref) => (
// setIsCheckboxChecked is here to remove it from the DOM element
<S.InputRadio
id={value}
name={name}
Expand All @@ -17,7 +16,7 @@ export const InputRadio = forwardRef(({ name, order, value, ...rest }, ref) => {
{...radio}
/>
)
})
)

InputRadio.type = 'InputRadio'
InputRadio.displayName = 'InputRadio'
Expand All @@ -33,6 +32,8 @@ InputRadio.propTypes = {
onFocus: func,
onKeyDown: func,
order: number,
radio: object,
setIsCheckboxChecked: func,
type: string,
value: string
}
21 changes: 14 additions & 7 deletions src/components/RadioGroup/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import React, { cloneElement } from 'react'
import { bool, node, string } from 'prop-types'
import { RadioGroup as ReakitRadioGroup, useRadioState } from 'reakit/Radio'

import { DIRECTIONS_TYPE } from '../../utils'
import { FieldGroup } from '../FieldGroup'

import * as S from './styles'

export const RadioGroup = ({ children, flexDirection, label, required }) => (
<FieldGroup label={label} required={required}>
<S.Radios flexDirection={flexDirection}>
{children.map(child => cloneElement(child, { key: child.props.value, flexDirection }))}
</S.Radios>
</FieldGroup>
)
export const RadioGroup = ({ children, flexDirection, label, required }) => {
const radio = useRadioState()

return (
<FieldGroup as={ReakitRadioGroup} label={label} required={required}>
<S.Radios flexDirection={flexDirection}>
{children.map(child =>
cloneElement(child, { key: child.props.value, flexDirection, radio: { ...radio } })
)}
</S.Radios>
</FieldGroup>
)
}

RadioGroup.propTypes = {
children: node,
Expand Down

1 comment on commit 16afd5d

@vercel
Copy link

@vercel vercel bot commented on 16afd5d Aug 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.