Home > front end >  Rendering array data with a condition
Rendering array data with a condition

Time:10-12

I need to make a large number of inputs and transfer this data to the server, I decided that the best solution would be to write all the options of these inputs into an array of objects, but I ran into the fact that I can’t get all my inputs to work. help me please

  const test = [
    {id: 1,state: 'city'},
    {id: 2,state: 'language'},
    {id: 3,state: 'brand'},
    {id: 4,state: 'shop'},
  ]
const Auth = () => {
  const [description, setDescription] = useState({city: "", language: "", brand: "", shop: ""});

const handleClick = async (event: any) => {
      await store.update(description.city, description.brand);
  };

const update = async (e: ChangeEvent<HTMLInputElement>) => {
      setDescription({
        ...description,
        city: e.target.value
      });
  };

return (
        <>
          {test.map(({ state, id}) => (
                <TextField
                    key={id}
                    label={state}
                    id={state}
                    autoComplete="off"
                    variant="outlined"
                    className={styles.textFieldAuth}
                    helperText={state}
                    value={description.city}
                    onChange={update}
                />
          ))}
             <Button
              className={styles.saveButton}
              variant="contained"
              color="inherit"
              id="login"
              onClick={handleClick}
             >
              Save
              </Button>
        </>
)
}

CodePudding user response:

Pass both the key that you want to update and the value to the update function:

const update = (key: string, value: string) => {
    setDescription({
        ...description,
        [key]: value,
    });
};


{test.map(({ state, id }) => (
    <TextField
        key={id}
        label={state}
        id={state}
        autoComplete="off"
        variant="outlined"
        className={styles.textFieldAuth}
        helperText={state}
        value={description.city}
        onChange={(e: ChangeEvent<HTMLInputElement>) =>
            update(state, e.target.value)
        }
    />
))}

CodePudding user response:

if you want to make it dynamic you would have to send the variable to save to your update method and retrieve your value with description[state]

  <TextField
    key={id}
    label={state}
    id={state}
    autoComplete="off"
    variant="outlined"
    className={styles.textFieldAuth}
    helperText={state}
    value={description[state]}
    onChange={(e)=>update(e, state)}
  />



 const update = async (e: ChangeEvent<HTMLInputElement>, state) => {
          setDescription({
            ...description,
            [state]: e.target.value
          });
    };

CodePudding user response:

You send to TextField description.city for every input. The correct props are like so:

                 <TextField
                    key={id}
                    label={state}
                    id={state}
                    autoComplete="off"
                    variant="outlined"
                    className={styles.textFieldAuth}
                    helperText={state}
                    value={description[state]}
                    onChange={update}
                />

See the change in the value prop.

Also, you are only update city in the update function. You have to make it so that the update function adapts to what values you pass to it. If you pass the city then it should update the city, if the language then the language and so on.

Overall this is not a good way to implement inputs. I just suggest you do them one by one and send to each TextField its corresponding value and a separate setState for each one.

But just for the sake of the example. The way you can do it is by passing the state value to the Update function.

So your function will look like this:

const update = async (e: ChangeEvent<HTMLInputElement>, state) => {
      setDescription((description) => {
        ...description,
        [state]: e.target.value
      });
  };

Now you just need to make sure that in the TextField component when you call onChange, you pass to it the event e and state which you have received from props.

Note: If you want to use the value of a state variable in the setState itself, pass to it a callback function like I did in the setDescription

CodePudding user response:

I think first and foremost you need your configuration data to try and closely match the elements you're building. So instead of { id, state } use { id, type, name }.

(This may not have a huge effect on your example because you're specifically using a TextField component, but if you were using native HTML controls you could add in different input types like number, email, date etc, and your JSX could deal with it easily.)

Second, as I mentioned in the comments, you don't need for those functions to be async - for example, there's no "after" code in handleClick so there's no need to await anything.

So here's a working example based on your code. Note: I've stripped out the Typescript (because the snippet won't understand the syntax), and the references to the UI components you're using (because I don't know where they're from).

const { useState } = React;

// So, lets pass in out inputs config
function Example({ inputs }) {
  
  // I've called the state "form" here as it's a little
  // more meaningful
  const [form, setForm] = useState({});

  // `handleSave` is no longer `async`, and for the
  // purposes of this example just logs the updated
  // form state
  function handleSave() {
    console.log(form);
    // store.update(form);
  }

  // Also no longer `async` `handleChange` destructures
  // the name and value from the changed input, and updates
  // the form state - a key wrapped with `[]` is a dynamic key
  // which means you can use the value of `name` as the key value
  function handleChange(e) {
    const { name, value } = e.target;
    setForm({ ...form, [name]: value });
  }

  // In our JSX we destructure out the id, name, and
  // type properties from each input object in the config
  // and apply them to the various input element properties.
  return (
    <div>
      {inputs.map(input => {
        const { id, name, type } = input; 
        return (
          <input
            key={id}
            type={type}
            name={name}
            placeholder={name}
            value={form[name]}
            onChange={handleChange}
          />
        );
      })}
      <button onClick={handleSave}>Save</button>
    </div>
  );

}

// Our updated config data
const inputs = [
  { id: 1, type: 'text', name: 'city' },
  { id: 2, type: 'text', name: 'language' },
  { id: 3, type: 'text', name: 'brand' },
  { id: 4, type: 'text', name: 'shop' }
];


ReactDOM.render(
  <Example inputs={inputs} />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

  • Related