প্রতিক্রিয়া + রেডাক্স - ফর্ম উপাদানগুলিতে সিআরইউডি হ্যান্ডেল করার সর্বোত্তম উপায় কী?


128

আমি একটি ফর্ম পেয়েছি যা তৈরি করতে, পড়তে, আপডেট করতে এবং মুছতে ব্যবহৃত হয়। আমি একই ফর্মের সাথে 3 টি উপাদান তৈরি করেছি তবে আমি তাদের পৃথক প্রপসগুলি দিয়েছি। আমি ক্রেডিটফর্ম.জেএস, ভিউফর্ম.জেএস (মুছুন বোতাম সহ কেবলমাত্র) এবং আপডেটফরম.জেএস পেয়েছি।

আমি পিএইচপি এর সাথে কাজ করতাম, তাই আমি সর্বদা এগুলি এক আকারে করতাম।

আমি দোকানটি পরিচালনা করতে প্রতিক্রিয়া এবং রেডাক্স ব্যবহার করি।

আমি যখন ক্রিয়েটফর্ম উপাদানটিতে থাকি, আমি আমার উপ-উপাদানগুলিতে এই মানগুলি createForm={true}দিয়ে কোনও মূল্য দিয়ে ইনপুটগুলি পূরণ না করার এবং তাদের অক্ষম না করার জন্য প্রপস করি। আমার ভিউফর্ম উপাদানটিতে, আমি এই প্রপসগুলি পাস করি readonly="readonly"

এবং আমি একটি টেক্সেরিয়া নিয়ে আর একটি সমস্যা পেয়েছি যারা মান সহ পূর্ণ এবং আপডেটযোগ্য নয়। মান সহ পাঠ্য প্রতিক্রিয়া কেবল পাঠযোগ্য তবে আপডেট করা দরকার

ফর্মের এই বিভিন্ন রাজ্য পরিচালনা করে এমন একটি উপাদান রয়েছে এমন সর্বোত্তম কাঠামো কী?

ভাগ করার জন্য আপনার কি কোনও পরামর্শ, টিউটোরিয়াল, ভিডিও, ডেমো আছে?

উত্তর:


115

আমি রেডাক্স ফর্ম প্যাকেজটি পেয়েছি । এটি সত্যিই ভাল কাজ করে!

সুতরাং, আপনি ব্যবহার করতে পারেন Redux সঙ্গে প্রতিক্রিয়া-Redux

প্রথমে আপনাকে একটি ফর্ম উপাদান তৈরি করতে হবে (স্পষ্টতই):

import React from 'react';
import { reduxForm } from 'redux-form';
import validateContact from '../utils/validateContact';

class ContactForm extends React.Component {
  render() {
    const { fields: {name, address, phone}, handleSubmit } = this.props;
    return (
      <form onSubmit={handleSubmit}>
        <label>Name</label>
        <input type="text" {...name}/>
        {name.error && name.touched && <div>{name.error}</div>}

        <label>Address</label>
        <input type="text" {...address} />
        {address.error && address.touched && <div>{address.error}</div>}

        <label>Phone</label>
        <input type="text" {...phone}/>
        {phone.error && phone.touched && <div>{phone.error}</div>}

        <button onClick={handleSubmit}>Submit</button>
      </form>
    );
  }
}

ContactForm = reduxForm({
  form: 'contact',                      // the name of your form and the key to
                                        // where your form's state will be mounted
  fields: ['name', 'address', 'phone'], // a list of all your fields in your form
  validate: validateContact             // a synchronous validation function
})(ContactForm);

export default ContactForm;

এর পরে, আপনি ফর্মটি পরিচালনা করে এমন উপাদানটি সংযুক্ত করুন:

import React from 'react';
import { connect } from 'react-redux';
import { initialize } from 'redux-form';
import ContactForm from './ContactForm.react';

class App extends React.Component {

  handleSubmit(data) {
    console.log('Submission received!', data);
    this.props.dispatch(initialize('contact', {})); // clear form
  }

  render() {
    return (
      <div id="app">
        <h1>App</h1>
        <ContactForm onSubmit={this.handleSubmit.bind(this)}/>
      </div>
    );
  }

}

export default connect()(App);

এবং আপনার সম্মিলিত হ্রাসকারীগুলিতে রিডেক্স-ফর্ম হ্রাসকারী যুক্ত করুন:

import { combineReducers } from 'redux';
import { appReducer } from './app-reducers';
import { reducer as formReducer } from 'redux-form';

let reducers = combineReducers({
  appReducer, form: formReducer // this is the form reducer
});

export default reducers;

এবং বৈধকরণকারী মডিউলটি এর মতো দেখাচ্ছে:

export default function validateContact(data, props) {
  const errors = {};
  if(!data.name) {
    errors.name = 'Required';
  }
  if(data.address && data.address.length > 50) {
    errors.address = 'Must be fewer than 50 characters';
  }
  if(!data.phone) {
    errors.phone = 'Required';
  } else if(!/\d{3}-\d{3}-\d{4}/.test(data.phone)) {
    errors.phone = 'Phone must match the form "999-999-9999"'
  }
  return errors;
}

ফর্মটি সম্পূর্ণ হওয়ার পরে, আপনি কিছু মান সহ সমস্ত ক্ষেত্র পূরণ করতে চাইলে আপনি এই initializeফাংশনটি ব্যবহার করতে পারেন :

componentWillMount() {
  this.props.dispatch(initialize('contact', {
    name: 'test'
  }, ['name', 'address', 'phone']));
}

ফর্মগুলি পপুলেট করার আরেকটি উপায় হ'ল প্রাথমিক ভ্যালু সেট করা।

ContactForm = reduxForm({
  form: 'contact',                      // the name of your form and the key to
  fields: ['name', 'address', 'phone'], // a list of all your fields in your form
  validate: validateContact             // a synchronous validation function
}, state => ({
  initialValues: {
    name: state.user.name,
    address: state.user.address,
    phone: state.user.phone,
  },
}))(ContactForm);

আপনি যদি এটি পরিচালনা করতে অন্য কোনও উপায় পেয়ে থাকেন তবে কেবল একটি বার্তা রাখুন! ধন্যবাদ.


3
শুধু ভাবছি - আপনি এখনও ব্যবহার করছেন redux-forms? আমি ভাবছি কীভাবে সেই বয়লারপ্লেটগুলি স্কেলগুলি প্রতিক্রিয়া ফর্মগুলির সাথে তুলনা করে
অ্যাশলি কুলম্যান

2
হ্যাঁ আমি এখনও এটি ব্যবহার করছি! সত্যিই দুর্দান্ত, আমি খুব বড় আকার তৈরি করেছি এবং এটি # 1 কাজ করেছে। আপনার উপাদানগুলি এবং তাদের আপডেটগুলিতে প্রপস হিসাবে আপনি যা পাস করেন সে সম্পর্কে আপনাকে খুব সতর্কতা অবলম্বন করতে হবে। উত্তর দেরি করার জন্য দুঃখিত।
মাইক বুটিন

1
@ মাইকবাউটিন আপনি কি প্রপস সম্পর্কে এই সতর্কতার সাথে বিস্তারিত বলতে পারবেন? ধন্যবাদ
আদম কে ডিন

এটি এতই এমনকি v6.4.3 থেকে আপনি এটি ব্যবহার করছেন ইশারা মূল্য পূর্ণ সম্ভাবনা আছে, কর্মক্ষমতা redux-formহয় অতল এজ সহ আই ই এর সব সংস্করণ, উপর। যদি আপনাকে এটি সমর্থন করতে হয়, তবে অন্যদিকে দেখুন।
স্টিফেন কলিন্স

2
আপনার ফর্মগুলিতে লগ তৈরি না করার জন্য এটি কেবলমাত্র কম্পোনেন্ট আপডেটের সাথে খুব কঠোর হতে হবে
মাইক বউটিন

11

আপডেট: এর 2018 এবং আমি কেবল কখনও ফর্মিক (বা ফর্মিকের মতো লাইব্রেরি) ব্যবহার করব

এছাড়াও প্রতিক্রিয়া-রিডেক্স-ফর্ম ( ধাপে ধাপে ) রয়েছে, যা মার্কআপ ঘোষণার সাথে রিডেক্স-ফর্মের কিছু জাভাস্ক্রিপ্ট (& বয়লারপ্লেট) বিনিময় করে বলে মনে হচ্ছে । এটি দেখতে দুর্দান্ত লাগছে, তবে আমি এখনও এটি ব্যবহার করি নি।

রিডমি থেকে কাটা এবং পেস্ট করুন:

import React from 'react';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { modelReducer, formReducer } from 'react-redux-form';

import MyForm from './components/my-form-component';

const store = createStore(combineReducers({
  user: modelReducer('user', { name: '' }),
  userForm: formReducer('user')
}));

class App extends React.Component {
  render() {
    return (
      <Provider store={ store }>
        <MyForm />
      </Provider>
    );
  }
}

./components/my-form-component.js

import React from 'react';
import { connect } from 'react-redux';
import { Field, Form } from 'react-redux-form';

class MyForm extends React.Component {
  handleSubmit(val) {
    // Do anything you want with the form value
    console.log(val);
  }

  render() {
    let { user } = this.props;

    return (
      <Form model="user" onSubmit={(val) => this.handleSubmit(val)}>
        <h1>Hello, { user.name }!</h1>
        <Field model="user.name">
          <input type="text" />
        </Field>
        <button>Submit!</button>
      </Form>
    );
  }
}

export default connect(state => ({ user: state.user }))(MyForm);

সম্পাদনা: তুলনা

প্রতিক্রিয়া-রিডেক্স-ফর্ম ডক্সটি তুলনা করে বনাম রিডেক্স-ফর্ম সরবরাহ করে:

https://davidkpiano.github.io/react-redux-form/docs/guides/compare-redux-form.html


4

যারা ফর্ম সম্পর্কিত সমস্যাগুলি পরিচালনা করার জন্য একটি বিশাল গ্রন্থাগার সম্পর্কে চিন্তা করেন না তাদের জন্য আমি রেডুএক্স-ফর্ম-ব্যবহারগুলি সুপারিশ করব ।

এটি আপনার ফর্ম নিয়ন্ত্রণের জন্য মান তৈরি করতে পারে এবং হ্যান্ডলারগুলি পরিবর্তন করতে পারে, ফর্মের হ্রাসকারী তৈরি করতে পারে, নির্দিষ্ট (বা সমস্ত) ক্ষেত্রগুলি পরিষ্কার করতে হ্যান্ডি অ্যাকশন নির্মাতারা ইত্যাদি etc.

আপনাকে যা করতে হবে তা হ'ল তাদের আপনার কোডে একত্রিত করা।

ব্যবহার করে redux-form-utils, আপনি নীচের মত ফর্ম হেরফের দিয়ে শেষ:

import { createForm } from 'redux-form-utils';

@createForm({
  form: 'my-form',
  fields: ['name', 'address', 'gender']
})
class Form extends React.Component {
  render() {
    const { name, address, gender } = this.props.fields;
    return (
      <form className="form">
        <input name="name" {...name} />
        <input name="address" {...address} />
        <select {...gender}>
          <option value="male" />
          <option value="female" />
        </select>
      </form>
    );
  }
}

যাইহোক, এই গ্রন্থাগার একমাত্র সমস্যা solves Cএবং Uজন্য, Rএবং D, হয়তো আরো একটি ইন্টিগ্রেটেড Tableকম্পোনেন্ট antipate হয়।


1

যারা বড় আকারের লাইব্রেরি ব্যবহার না করে সম্পূর্ণ নিয়ন্ত্রিত ফর্ম উপাদান তৈরি করতে চান তাদের জন্য কেবল একটি জিনিস thing

রেডাক্সফর্মহেল্পার - একটি ছোট ES6 শ্রেণি, 100 লাইনের চেয়ে কম:

class ReduxFormHelper {
  constructor(props = {}) {
    let {formModel, onUpdateForm} = props
    this.props = typeof formModel === 'object' &&
      typeof onUpdateForm === 'function' && {formModel, onUpdateForm}
  }

  resetForm (defaults = {}) {
    if (!this.props) return false
    let {formModel, onUpdateForm} = this.props
    let data = {}, errors = {_flag: false}
    for (let name in formModel) {
      data[name] = name in defaults? defaults[name] :
        ('default' in formModel[name]? formModel[name].default : '')
      errors[name] = false
    }
    onUpdateForm(data, errors)
  }

  processField (event) {
    if (!this.props || !event.target) return false
    let {formModel, onUpdateForm} = this.props
    let {name, value, error, within} = this._processField(event.target, formModel)
    let data = {}, errors = {_flag: false}
    if (name) {
      value !== false && within && (data[name] = value)
      errors[name] = error
    }
    onUpdateForm(data, errors)
    return !error && data
  }

  processForm (event) {
    if (!this.props || !event.target) return false
    let form = event.target
    if (!form || !form.elements) return false
    let fields = form.elements
    let {formModel, onUpdateForm} = this.props
    let data = {}, errors = {}, ret = {}, flag = false
    for (let n = fields.length, i = 0; i < n; i++) {
      let {name, value, error, within} = this._processField(fields[i], formModel)
      if (name) {
        value !== false && within && (data[name] = value)
        value !== false && !error && (ret[name] = value)
        errors[name] = error
        error && (flag = true)
      }
    }
    errors._flag = flag
    onUpdateForm(data, errors)
    return !flag && ret
  }

  _processField (field, formModel) {
    if (!field || !field.name || !('value' in field))
      return {name: false, value: false, error: false, within: false}
    let name = field.name
    let value = field.value
    if (!formModel || !formModel[name])
      return {name, value, error: false, within: false}
    let model = formModel[name]
    if (model.required && value === '')
      return {name, value, error: 'missing', within: true}
    if (model.validate && value !== '') {
      let fn = model.validate
      if (typeof fn === 'function' && !fn(value))
        return {name, value, error: 'invalid', within: true}
    }
    if (model.numeric && isNaN(value = Number(value)))
      return {name, value: 0, error: 'invalid', within: true}
    return {name, value, error: false, within: true}
  }
}

এটি আপনার জন্য সমস্ত কাজ করে না। তবে এটি নিয়ন্ত্রিত ফর্ম উপাদানটি তৈরি, বৈধকরণ এবং পরিচালনা করার সুবিধার্থে। আপনি কেবল উপরের কোডটি আপনার প্রকল্পে অনুলিপি করতে বা তার পরিবর্তে সম্পর্কিত লাইব্রেরি - redux-form-helper(প্লাগ!) অন্তর্ভুক্ত করতে পারেন।

ব্যবহারবিধি

প্রথম পদক্ষেপটি হ'ল রেডাক্স রাজ্যে নির্দিষ্ট ডেটা যুক্ত করা যা আমাদের ফর্মের রাজ্যের প্রতিনিধিত্ব করবে। এই ডেটাগুলির মধ্যে বর্তমান ক্ষেত্রের মানগুলি পাশাপাশি ফর্মের প্রতিটি ক্ষেত্রের জন্য ত্রুটিযুক্ত পতাকাগুলির সেট অন্তর্ভুক্ত থাকবে।

ফর্ম রাজ্যটি কোনও বিদ্যমান রিডুসারে যুক্ত করা যেতে পারে বা একটি পৃথক রিডুসারে সংজ্ঞায়িত করা যেতে পারে।

তদ্ব্যতীত ফর্মের রাজ্যের পাশাপাশি স্বতন্ত্র ক্রিয়া নির্মাতাকে নির্দিষ্ট ক্রিয়াকলাপের আপডেটের সংজ্ঞা দেওয়া প্রয়োজন।

ক্রিয়া উদাহরণ :

export const FORM_UPDATE = 'FORM_UPDATE' 

export const doFormUpdate = (data, errors) => {
  return { type: FORM_UPDATE, data, errors }
}
...

হ্রাস উদাহরণ :

...
const initialState = {
  formData: {
    field1: '',
    ...
  },
  formErrors: {
  },
  ...
}

export default function reducer (state = initialState, action) {
  switch (action.type) {
    case FORM_UPDATE:
      return {
        ...ret,
        formData: Object.assign({}, formData, action.data || {}),
        formErrors: Object.assign({}, formErrors, action.errors || {})
      }
    ...
  }
}

দ্বিতীয় এবং চূড়ান্ত পদক্ষেপটি হ'ল আমাদের ফর্মের জন্য একটি ধারক উপাদান তৈরি করা এবং এটি রেডাক্স রাজ্য এবং ক্রিয়াগুলির সংশ্লিষ্ট অংশের সাথে সংযুক্ত করুন।

এছাড়াও আমাদের ফর্ম ক্ষেত্রগুলির বৈধতা উল্লেখ করে একটি ফর্ম মডেল নির্ধারণ করতে হবে। এখন আমরা ReduxFormHelperউপাদানটির সদস্য হিসাবে অবজেক্টটি ইনস্ট্যান্ট করি এবং সেখানে আমাদের ফর্ম মডেল এবং ফর্মের স্থিতির একটি কলব্যাক প্রেরণযোগ্য আপডেটটি পাস করি।

তারপরে উপাদানটির render()পদ্ধতিতে আমাদের প্রতিটি ক্ষেত্রের onChangeএবং ফর্মের onSubmitইভেন্টগুলি যথাযথভাবে processField()এবং processForm()পদ্ধতিগুলির সাথে আবদ্ধ করতে হবে এবং রাজ্যের ফর্ম ত্রুটির পতাকাগুলির উপর নির্ভর করে প্রতিটি ক্ষেত্রের জন্য ত্রুটি ব্লক প্রদর্শন করতে হবে।

নীচের উদাহরণটি টুইটার বুটস্ট্র্যাপ ফ্রেমওয়ার্ক থেকে সিএসএস ব্যবহার করে।

ধারক উপাদান উদাহরণ :

import React, {Component} from 'react';
import {connect} from 'react-redux'
import ReduxFormHelper from 'redux-form-helper'

class MyForm extends Component {
  constructor(props) {
    super(props);
    this.helper = new ReduxFormHelper(props)
    this.helper.resetForm();
  }

  onChange(e) {
    this.helper.processField(e)
  }

  onSubmit(e) {
    e.preventDefault()
    let {onSubmitForm} = this.props
    let ret = this.helper.processForm(e)
    ret && onSubmitForm(ret)
  }

  render() {
    let {formData, formErrors} = this.props
    return (
  <div>
    {!!formErrors._flag &&
      <div className="alert" role="alert">
        Form has one or more errors.
      </div>
    }
    <form onSubmit={this.onSubmit.bind(this)} >
      <div className={'form-group' + (formErrors['field1']? ' has-error': '')}>
        <label>Field 1 *</label>
        <input type="text" name="field1" value={formData.field1} onChange={this.onChange.bind(this)} className="form-control" />
        {!!formErrors['field1'] &&
        <span className="help-block">
          {formErrors['field1'] === 'invalid'? 'Must be a string of 2-50 characters' : 'Required field'}
        </span>
        }
      </div>
      ...
      <button type="submit" className="btn btn-default">Submit</button>
    </form>
  </div>
    )
  }
}

const formModel = {
  field1: {
    required: true,
    validate: (value) => value.length >= 2 && value.length <= 50
  },
  ...
}

function mapStateToProps (state) {
  return {
    formData: state.formData, formErrors: state.formErrors,
    formModel
  }
}

function mapDispatchToProps (dispatch) {
  return {
    onUpdateForm: (data, errors) => {
      dispatch(doFormUpdate(data, errors))
    },
    onSubmitForm: (data) => {
      // dispatch some action which somehow updates state with form data
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyForm)

ডেমো

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.