qasimmehdi
qasimmehdi

Reputation: 376

How to create an event similar to onChange in React

I have a react native input component that takes a regex and emit a boolean if the regex matches.

I wanted to do the similar thing but return a string value in React Js but the problem is I don't totally understand how the react native input component is working.

Custom Input component

class CustomInput extends Component {
      handleValidation(value) {
        const {pattern} = this.props;
        if (!pattern) {
          return true;
        }
        // string pattern, one validation rule
        if (typeof pattern === 'string') {
          const condition = new RegExp(pattern, 'g');
          return condition.test(value);
        }
        // array patterns, multiple validation rules
        if (typeof pattern === 'object') {
          const conditions = pattern.map(rule => new RegExp(rule, 'g'));
          return conditions.map(condition => condition.test(value));
        }
      }
      onChange(value) {
        const {onChangeText, onValidation} = this.props;
        const isValid = this.handleValidation(value);
        onValidation && onValidation(isValid);
        onChangeText && onChangeText(value);
      }
      render() {
        const {pattern, onChangeText, children, style, ...props} = this.props;
        return (
          <Input
            style={style}
            onChangeText={value => this.onChange(value)}
            {...props}
            autoCapitalize="none">
            {children}
          </Input>
        );
      }
    }

Usage

<CustomInput
   value={pass}   //state variable
   onChangeText={onChangePass}   //state variable setter
   pattern={[regexes.password]}
   onValidation={isValid => performValidation(isValid)}
   //performValidatio method enables and disables a button according to  isValid
/>

Now I want to make a component in ReactJs that has an Input and other elements the input will take a regex and and it will return the value of its input to the parent. It will be used in a form that will have many inputs and all inputs need to have and error msg and validations.

Upvotes: 1

Views: 1465

Answers (2)

xdeepakv
xdeepakv

Reputation: 8135

You can create custom component with controlled state. You need to set local state within the custom component. On change of value, you can parse and validate. after that set it to local state. You can leverage error either local of delegate to parent. Here below sample, i have delegated to parent on validation.

const Input = ({
  onChangeText,
  pattern,
  onValidation,
  defaultValue,
  error,
  ...rest
}) => {
  const [value, setValue] = useValue(defaultValue);
  const onChange = ({ target: { value } }) => {
    if (pattern) onValidation(pattern.test(value));
    setValue(value);
    onChangeText(value);
  };
  return (
    <div className="wrapper">
      <input value={value} onChange={onChange} {...rest} />
      {error && <span>{error}</span>}
    </div>
  );
};

Upvotes: 1

qasimmehdi
qasimmehdi

Reputation: 376

I have understood the logic if anyone wants to make an input like this they can use this code

I have used react-bootstrap for styling

The Custom Input

import React, { useState } from "react";

export default function CustomInput(props) {
  const { error, inputProps, regex, className, onInput } = props;
  const [showError, setShowError] = useState(false);
  const [text, setText] = useState("");
  const handleChange = (val) => {
    setText(val);
    if (regex.test(val)) {
      setShowError(false);
    } else {
      setShowError(true);
    }
    onInput && onInput(val);
  };
  return (
    <div className={className}>
      <input
        value={text}
        className={showError ? "form-control border-danger" : "form-control"}
        {...inputProps}
        onChange={(e) => handleChange(e.target.value)}
      />
      {showError && error ? (
        <small className="text-danger">{error}</small>
      ) : null}
    </div>
  );
}

And use it in a parent component like this

const [temp, setTemp] = useState("");

<CustomInput
  className="form-group col-md-3"
  inputProps={{ placeholder: "test", maxLength: "50" }}
  error="Required"
  regex={regexes.url}
  onInput={(val) => setTemp(val)}
/>

Somebody please confirm if this is a good approach

Upvotes: 0

Related Questions