user12130378
user12130378

Reputation:

how to watch field in react (dynamically add useEffect)?

I am trying to watch a field which have watch:true field.In other words I want add useEffect dynamically.I have one json (which is coming from server).I want to watch field value (which have property watch:true).using it's value I want to update other field value .

here is my code

https://codesandbox.io/s/crimson-violet-uxbzd

see this object have watch: true, so I need to watch or check if it value is changed or not

 {
     label: "First",
     name: "first",
     type: "select",
     remove: true,
     watch: true,
     options: ["", "one", "two"]
},

if it's value is changed then call this function

const getSecondDropdownValue = function(value) {
    return new Promise((resolve, reject) => {
      if (value === "one") {
        setTimeout(function() {
          resolve(["three", "four"]);
        }, 1000);
      }

      if (value === "two") {
        setTimeout(function() {
          resolve(["five", "six"]);
        }, 1000);
      }
    });
  };

any update?.

Upvotes: 2

Views: 1284

Answers (1)

Junius L
Junius L

Reputation: 16122

Check if the item has watch property, if it does pass getSecondDropdownValue to onChange event of the select option. something like

<select onChange={hasWatch ? getSecondDropdownValue : () => {}}>...</select>

Create a component that will render select options.

// options = array of list options
// onChange = onchange event handler
// name = name of the select
const Option = ({ options, onChange, name }) =>
  (options.length && (
    <select onChange={(e) => onChange(e.target.value, name)}>
      {Array.isArray(options) &&
        options.map((option, index) => (
          <option value={option} key={option + index}>{option}</option>
        ))}
    </select>
  )) ||
  false;

Add useState for storing the data from the api.

// initial data from the api
const [data, updateData] = useState(apiData);

// update select options and the list
const updateSelectData = (list, updated) => {

    const index = list.findIndex(item => item.name === updated.name);
    return [
      ...list.slice(0, index),
      Object.assign({}, list[index], updated),
      ...list.slice(index + 1)
    ];
  };

getSecondDropdownValue function

const getSecondDropdownValue = function(value, name) {
  const updated = data.find(
    item => item.dependentField && item.dependentField[0] === name
  );

  // return new Promise((resolve, reject) => {
  if (value === "one") {
    // setTimeout(function() {
    // resolve(["three", "four"]);
    // }, 1000);
    updated.options = ["three", "four"];
  }

  if (value === "two") {
    // setTimeout(function() {
    // resolve(["five", "six"]);
    // }, 1000);
    updated.options = ["five", "six"];
  }
  // });

  updateData(updateSelectData(data, updated));
};

Example

// Get a hook function
const {useState} = React;

const apiData = [
    {
      label: "First",
      name: "first",
      type: "select",
      watch: true,
      options: ["", "one", "two"]
    },
    {
      label: "Second",
      name: "second",
      options: [],
      dependentField: ["first"],
      type: "select"
    }
  ];
  
// option component  
const Option = ({ options, onChange, name }) =>
  (options.length && (
    <select onChange={(e) => onChange(e.target.value, name)}>
      {Array.isArray(options) &&
        options.map((option, index) => (
          <option value={option} key={option + index}>{option}</option>
        ))}
    </select>
  )) ||
  false;

function App() {

  const [data, updateData] = useState(apiData);

  const updateSelectData = (list, updated) => {
    const index = list.findIndex(item => item.name === updated.name);
    return [
      ...list.slice(0, index),
      Object.assign({}, list[index], updated),
      ...list.slice(index + 1)
    ];
  };

  const getSecondDropdownValue = function(value, name) {
    const updated = data.find(
      item => item.dependentField && item.dependentField[0] === name
    );

    // return new Promise((resolve, reject) => {
    if (value === "one") {
      // setTimeout(function() {
      // resolve(["three", "four"]);
      // }, 1000);
      updated.options = ["three", "four"];
    }

    if (value === "two") {
      // setTimeout(function() {
      // resolve(["five", "six"]);
      // }, 1000);
      updated.options = ["five", "six"];
    }
    // });

    updateData(updateSelectData(data, updated));
  };

  return (
    <div className="App">
      {data.map((options, index) => (
        <Option
          name={options.name}
          key={index}
          onChange={options.watch ? getSecondDropdownValue : () => {}}
          options={options.options}
        />
      ))}
    </div>
  );
}
// Render it
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Upvotes: 1

Related Questions