Skip to content
This repository has been archived by the owner on Dec 2, 2023. It is now read-only.

Commit

Permalink
improve render while still keeping logic refreshes
Browse files Browse the repository at this point in the history
  • Loading branch information
wodka committed Mar 1, 2022
1 parent fe51c52 commit 4c8ca21
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- edit user shows now email in title
- focus is now passed also do slide layout fields
- empty fields are no longer submitted
- stuttery form because of logic rerenders

### Security

Expand Down
73 changes: 45 additions & 28 deletions components/form/layouts/card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { darken, lighten } from 'polished'
import React, { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { FormPublicFieldFragment } from '../../../../graphql/fragment/form.public.fragment'
import { Omf } from '../../../omf'
import { StyledButton } from '../../../styled/button'
import { useMath } from '../../../use.math'
import { fieldTypes } from '../../types'
import { LayoutProps } from '../layout.props'
import { Field } from './field'
import { Page } from './page'
Expand Down Expand Up @@ -39,7 +39,7 @@ export const CardLayout: React.FC<LayoutProps> = (props) => {
const [loading, setLoading] = useState(false)
const [step, setStep] = useState<Step>(props.form.startPage.show ? 'start' : 'form')
const evaluator = useMath()
const [values, setValues] = useState({})
const [visiblity, setVisibility] = useState({})

const { design, startPage, endPage, fields } = props.form
const { setField } = props.submission
Expand All @@ -48,7 +48,9 @@ export const CardLayout: React.FC<LayoutProps> = (props) => {
const defaults = {}

fields.forEach(field => {
const defaultValue = field.defaultValue ? JSON.parse(field.defaultValue) : null
const defaultValue = field.defaultValue
? fieldTypes[field.type].parseValue(field.defaultValue)
: null

defaults[`@${field.id}`] = form.getFieldValue([field.id, 'value']) ?? defaultValue

Expand All @@ -57,8 +59,43 @@ export const CardLayout: React.FC<LayoutProps> = (props) => {
}
})

setValues(defaults)
}, [fields, form])
// now calculate visibility
const nextVisibility = {}
fields.forEach(field => {
if (!field.logic) return

const logic = field.logic
.filter(logic => logic.action === 'visible')

if (logic.length === 0) {
return
}

nextVisibility[field.id] = logic
.map(logic => {
try {
const r = evaluator(
logic.formula,
defaults
)

return Boolean(r)
} catch {
return true
}
})
.reduce<boolean>((previous, current) => previous && current, true)
})

// TODO improve logic of how we calculate new logic checks
if (Object.values(nextVisibility).join(',') == Object.values(visiblity).join(',')) {
return
}

setVisibility(nextVisibility)
}, [
fields, form, visiblity,
])

useEffect(() => {
updateValues()
Expand Down Expand Up @@ -95,27 +132,7 @@ export const CardLayout: React.FC<LayoutProps> = (props) => {
setLoading(false)
}

const isVisible = useCallback((field: FormPublicFieldFragment): boolean => {
if (!field.logic) return true

return field.logic
.filter(logic => logic.action === 'visible')
.map(logic => {
try {
const r = evaluator(
logic.formula,
values
)

return Boolean(r)
} catch {
return true
}
})
.reduce<boolean>((previous, current) => previous && current, true)
}, [
fields, form, values,
])
console.log('render')

const render = () => {
switch (step) {
Expand All @@ -130,12 +147,12 @@ export const CardLayout: React.FC<LayoutProps> = (props) => {
onFinish={finish}
onValuesChange={updateValues}
>
{fields.map((field, i) => {
{fields.map((field) => {
if (field.type === 'hidden') {
return null
}

if (!isVisible(field)) {
if (visiblity[field.id] === false) {
return null
}

Expand Down
2 changes: 2 additions & 0 deletions components/form/types/image/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
import dynamic from 'next/dynamic'
import { ComponentType } from 'react'
import { AbstractType } from '../abstract.type'
Expand All @@ -13,3 +14,4 @@ export class ImageType extends AbstractType<string> {
return dynamic(() => import('./dropdown.input').then(c => c.builder(this)));
}
}
*/

0 comments on commit 4c8ca21

Please sign in to comment.