code_dude
code_dude

Reputation: 1111

How to make react input show state value?

I have title and message variables as the local state in my React component. The idea is that when the component mounts, these two variables get initialised either with the respective values coming from currentPost object which is coming from Redux, or otherwise with an empty string.

const MyComponent = ({ currentPost }) => {
    const [title, setTitle] = React.useState(currentPost.title ? currentPost.title : '');
    const [message, setMessage] = React.useState(currentPost.message ? currentPost.message : '');

    <form>
    <div className="form-group">
         <input
             value={title}
             onChange={evt => setTitle(evt.target.value)}
         />                   
    </div>

    <div className="form-group">
         <input
             value={title}
             onChange={evt => setTitle(evt.target.value)}
         />                   
    </div>
    </form>


    const mapStateToProps = state => ({ currentPost: state.posts.currentPost });
};

The code above is actually a modal that opens whenever I click on the edit icon of a given post. In the same time, the currentPost object on Redux state, which is empty, gets populated with the selected post. Then in the above modal component, I get currentPost from Redux state.

The problem is that the two variables always get an empty string, even when currentPost is populated with all the data I need. How can I make the input fields show the right data depending on the currentPost state?

Upvotes: 0

Views: 571

Answers (2)

Thales Kenne
Thales Kenne

Reputation: 2932

Your logic is correct, there is nothing wrong with it. Just notice that the useState will only be defined when the component renders for the FIRST time. Your redux state is probably being updated only after the component has mounted already.

A quick way of checking that is just to console.log before defining the state.

const MyComponent = ({ currentPost }) => {

    // This will probably show "undefined" in the first log
    console.log('current Post', currentPost);

    const [title, setTitle] = React.useState(currentPost.title ? currentPost.title : '');
    const [message, setMessage] = React.useState(currentPost.message ? currentPost.message : '');

    <form>
    <div className="form-group">
         <input
             value={title}
             onChange={evt => setTitle(evt.target.value)}
         />                   
    </div>

    <div className="form-group">
         <input
             value={title}
             onChange={evt => setTitle(evt.target.value)}
         />                   
    </div>
    </form>


    const mapStateToProps = state => ({ currentPost: state.posts.currentPost });
};

There are two ways of going about it. You can either use the redux state straight into the input and onChange will call a method to update that same state

OR

Use useEffect to update the local state once currentPost changes.

useEffect(() => {
    setTitle(currentPost.title);
    setMessage(currentPost.message);
}, [currentPost]);

Upvotes: 1

Aleksandr Kurilov
Aleksandr Kurilov

Reputation: 341

try this:

const [title, setTitle] = React.useState(
    currentPost.title && currentPost.title.length ? currentPost.title : ""
  );
  const [message, setMessage] = React.useState(
    currentPost.message && currentPost.message.length ? currentPost.message : ""
  );

The currentPost.title condition checks if there is a value in title or it is undefined, if you pass an empty string, then such a condition will return true, in order to check not only for the presence of a value, but also for the presence of some value in it, you can also check the length property, for strings this should work.

You can see the code here:

https://codesandbox.io/s/input-components-o02qg

UPD: Take a look this example, i make new SandBox, on redux and TS,

https://codesandbox.io/s/serverless-silence-f19lp?file=/src/MyComponent.tsx

P.S. Only I do not understand why create internal state in components, if the state of these components is stored in the Redux store.

P.P.S. Please show more code to understand more

Upvotes: 1

Related Questions