0

I'm trying to figure out how I can set a disabled field in a stateless component that only uses prop. The stateless component has a input field that if empty I would like to disable the submit button within the same component. I was able to update the parent's state via a prop to the child and so wanted to keep it with no state but starting to think I may need it for checking if the button can be enabled or not.

I've tried different methods using refs etc. Here is a codesandbox project I have for an example

https://codesandbox.io/s/840kkk03l

The stateless prop is :

const Childprop = function(props) {
  function handleNameChange(e) {
    e.preventDefault();
    props.onNameChange(e.target.newName.value);
  }
  function checkDisabled() {
    var input = document.getElementById("input");
    if (input.value === "") {
      return true;
    } else {
      return false;
    }
  }
  return (
    <p>
      The logged in user is: {props.nameProp}
      <form onSubmit={handleNameChange}>
        <input name="newName" type="text" id="input" />
        <input type="submit" disabled={checkDisabled} />
      </form>
    </p>
  );
};

Thank you

CI_Guy
  • 1,039
  • 2
  • 22
  • 39
  • you basically _need_ state for this to work (either in this component, or a parent component). Also, you can't assume `input#input` will be in the DOM when `checkDisabled` is called - use a `ref` instead. – Tyler Sebastian Aug 17 '18 at 20:06
  • Tried ref.. seems the ref is inaccessible/undefined to the call within disabled={} – CI_Guy Aug 17 '18 at 20:10

3 Answers3

1

I'd use a local state just for the value of the input. This would make it a controlled component.

class Childprop extends React.Component {
    state = {
        newName: ''
    }

    handleNameChange = (e) => {
        e.preventDefault();
        props.onNameChange(this.state.newName);
        this.setState({ newName: '' });
    }

    render() {
        return (
            <div>
                The logged in user is: {props.nameProp}
                <form onSubmit={handleNameChange}>
                    <input name="newName" type="text" id="input" onChange={(e) => this.setState(e.target.value)} value={this.state.newName} />
                    <input type="submit" disabled={this.state.newName.length === 0} />
                </form>
            </div>
        );
    }
};
ChezFre
  • 6,502
  • 1
  • 19
  • 25
  • 1
    You can use ref inside a stateless component: https://stackoverflow.com/a/40795623/235659 – Anas Aug 17 '18 at 20:17
  • 1
    You're right @Anas, I misread the documentation (https://reactjs.org/docs/refs-and-the-dom.html). Will update my answer. – ChezFre Aug 17 '18 at 20:21
0

This cannot be done. Something in your app must call setState, forceUpdate or the root application be re-rendered for your stateless function to be called again.

azium
  • 20,056
  • 7
  • 57
  • 79
  • So basically, use state even if for only the isDisabled? I'm learning React and tried to keep all state in the container component. – CI_Guy Aug 17 '18 at 20:12
  • i mean `disabled` is literally "a state".. it's either true or false.. the only reason you don't need that for `input` values is that DOM has its own internal state that you can piggy back off of, but in most react apps you use controlled inputs anyways – azium Aug 17 '18 at 20:39
0

You can make it work like this: https://codesandbox.io/s/rr6jw0xxko

The only issue is once the button is disabled, there is no way to enable it again since you cannot submit anymore.

I agree that @azium way is the React way.

Anas
  • 5,622
  • 5
  • 39
  • 71
  • 1
    The example you provided doesn't have the desired result either but it looks like I should be using state anyway. Thanks – CI_Guy Aug 17 '18 at 20:13