skip to Main Content

in app.js in which i have used single state to keep track of object with two key values but when i am selecting game its working fine but when selecting for day it is giving me error pls help

how to change one single key value in state

TypeError

Cannot read properties of null (reading ‘value’)

import React, { useState } from "react";

const options = ["cricket", "football", "hockey"];
const days = ["weekday", "weekend"];

function App() {
  const [otp, setOtp] = useState({ opts: "", das: "" });

  const chng = event => {
    setOtp(prevValues => {
      return { ...prevValues, opts: event.target.value };
    });
  };

  const chgd = event => {
    if (event.target && event.target.value) {
      setOtp(prevValues => {
        return { ...prevValues, das: event.target.value };
      });
    }
  };

  return (
    <div className="App">
      <h1>Which game</h1>
      {options.map(value => (
        <div key={value}>
          <input
            type="radio"
            name="options"
            id={value}
            value={value}
            onChange={chng}
          />
          <label htmlFor={value}>{value}</label>
        </div>
      ))}
      <h1>Which Day</h1>
      {days.map(value => (
        <div key={value}>
          <input
            type="radio"
            name="days"
            id={value}
            value={value}
            onChange={chgd}
          />
          <label htmlFor={value}>{value}</label>
        </div>
      ))}
      <p>Will Play {otp.opts} on {otp.das}</p>
    </div>
  );
}

export default App;

3

Answers


  1. Adding event.persist() to the beginning of each event handler fixes the problem:

      function chng(event) {
        event.persist()
    
        if (event?.target?.value) {
          setop((prev) => ({
            ...prev,
            opts: event.target.value
          }));
        }
      }
    

    This is because versions of React before 17 do something called event pooling, which sets event fields to null and attempts to reuse the object for performance in older browsers.

    This answer explains the problem in more detail.

    Login or Signup to reply.
  2. I think the problem comes when you set the setOtp function, try doing it this way and it works fine

    instead of

    setOtp(prevValues => {
            return { ...prevValues, das: event.target.value };
    

    you can do this

      function chgd(event) {
        if (event.target && event.target.value) {
          const pref = { ...otp };
          pref.das = event.target.value;
          setop(pref);
        } else {
          // Handle the case when event or event.target.value is null
          // You can choose to set a default value or handle it in a different way
        }
      }
    

    and you can make the same in chng function:

    function chng(event) {
        if (event.target && event.target.value) {
          const pref = { ...otp };
          pref.opts = event.target.value;
          setop(pref);
        } else {
          // Handle the case when event or event.target.value is null
          // You can choose to set a default value or handle it in a different way
        }
      }
    
    Login or Signup to reply.
  3. There is an easier way to think about what you are doing .. I’ve severely dumbed it down so that you can understand the setting and getting. I’ve removed the object from the state, and set two different states. This is just another way to look at it. This isn’t the way I would do it .. But I wanted you to see the function based code, in a ELI5 way, so you can see it working and all it’s individual pieces.

    Note, if you don’t need ANYTHING ELSE to happen in your chng() functions .. You can also just straight set the state from the onChange= event IE:

    onChange={(e) => setOtps(e.target.value)}
    

    without the need for external functions.

    import React, { useState } from "react";
    
    const options = ["cricket", "football", "hockey"];
    const days = ["weekday", "weekend"];
    
    function App() {
        const [otps, setOtps] = useState('');
        const [das, setDas] = useState('');
    
        function chng (e){
            setOtps(e);
            // Do other things ..  Axios etc
        }
    
        function chgd (e){
            setDas(e);
            // Do other things .. Axios etc
        }
    
        return (
            <div style={{marginLeft:"300px"}}>
            <div className="App">
                <h1>Which game</h1>
                {options.map(value => (
                    <div key={value}>
                        <input
                            type="radio"
                            name="options"
                            id={value}
                            defaultValue={value}
                            onChange={(e) => chng(e.target.value)}
                        />
                        <label htmlFor={value}>{value}</label>
                    </div>
                ))}
                <h1>Which Day</h1>
                {days.map(value => (
                    <div key={value}>
                        <input
                            type="radio"
                            name="days"
                            id={value}
                            defaultValue={value}
                            onChange={(e) => chgd(e.target.value)}
                        />
                        <label htmlFor={value}>{value}</label>
                    </div>
                ))}
                <hr />
                <p>Will Play <br />{otps} on {das}</p>
            </div>
            </div>
    
        );
    }
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search