The component has its own data management

Components can interact with forms without writing code by dumbing them up. This development is not very nice 🎉. That is in the hooks of my story.

🗒️ Component data controlled or uncontrolled

The component owns its own data without passing in data. This is an uncontrolled component at all, yes 🙃🙃🙃

The component code might look like this:

// components/test.jsx
import React, { useState } from 'react'
import { Button } from 'antd'
export default() = > {const [state, setState] = useState(0)
  return (
    <div>
      <p>{state}</p>
      <Button
        onClick={()= >{setState(state + 1)}} > Click add one</Button>
    </div>)}Copy the code

With an uncontrolled component, you don’t have to pass anything, the component has its own data and can interact with the user by itself.

import React from 'react'
import TT from 'components/test'
export default props => {
  return <Test />
}
Copy the code

The awkwardness of a controlled component is that there is no way to manipulate or retrieve the component’s data outside of the component; the component’s data is left to itself. What about controlled components? The code might look like this.

import React, { useState } from 'react'
import { Button } from 'antd'
export default props => {
  const { state, setState } = props
  return (
    <>
      <p>{state}</p>
      <Button
        onClick={()= >{setState(state + 1)}} > Click add one</Button>
    </>)}Copy the code

With controlled components, you need to do your own data state management in the parent component.

import React from 'react'
import TT from 'components/test'
export default props => {
  const [state, setState] = useState(0)
  return <Test state={state} setState={setState} />
}
Copy the code

Is it a controlled component or an uncontrolled component? With uncontrolled components, there is no way to access and interfere with component data. With controlled components, the parent component has to maintain its own data management. 👎👎, the component comes with data management 💣💣 👎. So this article is to give the perfect answer 👏👏, so that the component can be controlled without requiring the parent component to manage data.

Component interaction Design

The goal is for components to manipulate data without having to do data management. Consider the interaction design of a wave of antd4.0 forms.

UseForm to interact with the Form data field.

import React from 'react'
import { Form, Button } from 'antd'
export default() = > {const [form] = Form.useForm()
  return (
    <div>
      <Form form={form}>
        <Form.Item name="note" label="Note">
          <Input />
        </Form.Item>
      </Form>
      <Button
        type="primary"
        onClick={()= >{message.info(form.getFieldsValue('note'))}} > View data</Button>
      <Button
        type="primary"
        onClick={()= >{ form.setFieldsValue({ note: 'Hello world! '})}} > Modify data</Button>
    </div>)}Copy the code

**Form has its own data management, similar to the controlled components above. If the external component (parent component) wants to manipulate component data, use form.useForm (), such as getFieldsValue and setFieldsValue.

Designed and implemented

Antd4 form data interaction is implemented based on RC-Form. If we were to write a mid-platform component, how would we implement this logic? Write it yourself, of course, in a few lines of code. People, the code 🏇🏇.

If you know how to use it, it is easy to know how to implement it. Assume that EditableTags is the mid-stage component we want to develop, and its function is to add and delete tags.

import React from 'react'
importEditableTags, {useTags}from './tags'
import { Button } from 'antd'
export default() = > {let tagsHook = useTags()
  return (
    <div>
      <EditableTags
        defaultValue={['first ',' second ', 'third ',]}tagsHook={tagsHook}// It can be used to get dataonChangeGet / >
      <Button
        onClick={()= >{console.log("tags", taghook. getTags())}} > View</Button>
    </div>)}Copy the code

EditableTags component part of the code

**_store: ** Stores component data. All component data is stored in this store

TagsHook: function passed in by outer useTags, same as antd4 form

import { tagsInit, _store } from './store'

export default() = > {const [tags, setTags, index] = tagsInit(defaultValue)
  tagsHook && tagsHook(index)
  return <div>.</div>
}
Copy the code

. / store code

The core is the./store code.

_store

** parsing: ** returns a function that forms a closure. The main purpose is to preserve the index index and ensure that each component has its own unique index. _store is the data for all components.

function useTags() {
  let index = null // The component is called with an assignment
  let func = i= > {
    index = i
  }

  func.getTags = (a)= > {
    if (index === null) {
      throw new Error('your must set useTags to a Tags components property ')}return _store[index]
  }
  func.setTags = data= > {
    if (index === null) {
      throw new Error('your must set useTags to a Tags components property ')
    }
    _store[index] = data
  }

  return func
}
Copy the code

tagsInit

Each component data is initialized by tagsInit

import { useEffect, useState, useRef } from 'react'

const _store = {}
let _length = 0
function tagsInit(defaultValue) {
  let index = useRef(_length++).current

  const [data, setData] = useState(_store[index] || defaultValue || [])

  const setTags = data= > {
    setData(data)
    _store[index] = data
  }

  useEffect((a)= > {
    _store[index] = data
    // Delete the element to free memory
    return (a)= > {
      delete _store[index]
    }
  }, [])

  return [data, setTags, index]
}
Copy the code

Isn’t that easy? TagsInit +_store adds up to store files

✨ finally

Write well in the middle of the component interaction, the back end can also easily develop front-end business. The key is to design the interaction between the mid-platform components. Bytedance: High pay, top benefits. Resumes are welcome: [email protected]