0

react-final-form我有一些代码为外部 JSON API 返回的每个条目创建一个表单。

我试图使用一个变量i来设置一个Control'd Inputchakra 组件的名称。(此组件的定义是从带有脉轮示例的react-final-form 复制而来)。i将在来自 API 的数组项的循环中递增。这以某种方式导致了无限循环。(return语句中的这段代码在示例代码中有注释)

但是,如果我只设置没有i变量的名称,一切正常。

我试图理解为什么使用i会导致无限循环?

我想使用i某种方式会导致Form以某种方式改变状态/重新渲染,但我现在确定如何/为什么会发生这种情况?

这是重现问题的笔: https ://codepen.io/growinman/pen/GRmGyxX?editors=1010

(代码原样工作正常,但如果我使用注释返回语句,它会导致无限循环)

任何帮助,将不胜感激!

这是代码的内联副本:

import * as finalForm from "https://cdn.skypack.dev/final-form@4.20.2";
import { Form, useField } from  "https://cdn.skypack.dev/react-final-form@6.5.3";
import * as reactRouterDom from "https://cdn.skypack.dev/react-router-dom@5.2.0";
import * as React from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import { Input }    from "https://cdn.skypack.dev/@chakra-ui/input@1.2.8";
import { VStack }   from "https://cdn.skypack.dev/@chakra-ui/react@1.6.5";
import { Heading }   from "https://cdn.skypack.dev/@chakra-ui/layout@1.4.7";
import { FormControl, FormErrorMessage } from "https://cdn.skypack.dev/@chakra-ui/form-control@1.3.8";

async function handleErrors(response) {
  if (!response.ok) {
      throw await response.json();
  }
  return response;
}

const makeGetRequest = (requestUrl) => {
  const requestOptions = {
    method: 'GET'
  }

  return fetch(requestUrl, requestOptions)
  .then(handleErrors)
  .then((response) => {
    return response.json()
  })
}


const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

const onSubmit = async values => {
  await sleep(300)
  window.alert(JSON.stringify(values, 0, 2))
}


const ProductReview = (props) => {
    let i=0;
    console.log('rendering')
    const [unreviewedProducts, setUnreviewedProducts] = React.useState({})
    
    React.useEffect(
        () => {
            console.log('In useeffect')
            makeGetRequest('https://mocki.io/v1/aea3b014-5a38-4366-a71c-87b2e53eb07c').then(
              // Create a map for unreviewedProducts from the 'unreviewedProductsJson' array, keyed by the uuid
                (unreviewedProductsJson) => {
                    setUnreviewedProducts(
                        unreviewedProductsJson.reduce(
                            (mapSoFar, currentObj) => ({...mapSoFar, [currentObj.uuid]: currentObj}), {}
                        )
                    )
                }
            )
        },
        []
    )

    return (
        <>
            <Heading as="h1" fontSize={[16,32]} textAlign="center" marginTop="20px">
                Products
            </Heading>
            <VStack
                alignItems="stretch"
                margin="20px auto 0 auto"
                w="80%"
                maxW="600px"
            >
                {
                    Object.values(unreviewedProducts).map((unreviewedProduct) => {
                        console.log('In map()')
                        return (
                            <Form
                                key={unreviewedProduct.uuid}
                                onSubmit={onSubmit}
                                validate={() => {}}
                                render={({
                                handleSubmit,
                                form,
                                errors,
                                submitting,
                                pristine,
                                values
                                }) => {
                                    console.log('In render')
                                    console.log(i)
                                    i = i + 1
                                    
                                    return (
                                    <VStack
                                        marginTop="103px"
                                    >
                                        
                                        <InputControl name={unreviewedProduct.uuid} placeholder="Website" />
                                    </VStack>
                                )
                              
//                               return (
//                                     <VStack
//                                         marginTop="103px"
//                                     >
                                        
//                                         <InputControl name={i} placeholder="Website" />
//                                     </VStack>
//                                 )
                            }
                                    }
                            />
                        )
                    })
                }
            </VStack>
        </>
    )
}


// These were mainly copied from the chakra-ui/react-final-form example
// from here: https://final-form.org/docs/react-final-form/examples/chakra
const Control = ({ name, ...rest }) => {
    const {
        meta: { error, touched }
    } = useField(name, { subscription: { touched: true, error: true } })
    return <FormControl {...rest} isInvalid={error && touched} />
}


const Error = ({ name }) => {
    const {
        meta: { error }
    } = useField(name, { subscription: { error: true } })

    return <FormErrorMessage>{error}</FormErrorMessage>
}

const InputControl = ({ name }) => {
    const { input, meta } = useField(name)
    return (
      <>
        <Control name={name} my={4}>
            <Error name='s' />
            <Input
            {...input}
            isInvalid={meta.error && meta.touched}
            id={name}
            />
        </Control>
      </>
    )
  }

ReactDOM.render(<ProductReview />, document.getElementById('root'))
4

0 回答 0