Alexey
Alexey

Reputation: 227

React prevstate usage

I have a Cell component and when I click on it I want some popup window named ChangeParamWindow to appear. ChangeParamWindow has 2 buttons and if any of them was clicked I want to refresh value in the Cell to refresh from the popup input & ChangeParamWindow change its display to none if it is block (for hiding block). It hides itself succesfully only one time, but never again. I am pretty sure that using prevState somehow wrong, but could abybody tell me what I am doing wrong?

class ChangeParamWindow extends React.Component {
  constructor(props) {
    super(props)
    this.onClose = this.onClose.bind(this);
    this.state = {
      placeholder: "Param...",
      maxlength  : 100,
      inputType  : "text",
      type       : "any",  // number or string. (for restritions)
      value      : null,
      outline    : "none",
      position   : "absolute",
      display    : "block"
    }
    this.inputId = "small-window-input-id"
  }
  onClose(e) {
    e.preventDefault()
    let value = document.getElementById(this.inputId).value
    console.log("new value is", value)

    this.setState(prevState => ({
      display : (prevState.display == "none") ? "display" : "none", // TODO ???
      value   : value
    }))
  }
  render(){
    return (
        <div
        style={{
            display  : this.state.display,
            position : this.state.position,
            outline  : this.state.outline,
            left     : this.props.x,
            top      : this.props.y
        }}
        >
          <input
              id={this.inputId}
              maxLength={this.state.maxlength}
              type={this.state.inputType}
              placeholder={this.state.placeholder}
          />
          <input
              onClick={ this.onClose }
              type="submit"
              value="ok"
          />
          <input
              onClick={this.onClose }
              type="submit"
              value="cancel"
          />
        </div>
    )
  }
}

class Cell extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value   : null,
      type    : "any",
      noValue : "..."
    }
  }
  openChangeParamWindow(x, y) {
    ReactDOM.render(
        <ChangeParamWindow
          x={x}
          y={y}
        />,
        document.getElementById("change-param-window")
    )
  }
  isNumberValid() {

  }
  isStringValid() {

  }
  render() {
    let value = (this.state.value == null) ? this.state.noValue : this.state.value;
    return (
      <div
          className="cell"
          onClick={event => {
            this.openChangeParamWindow(event.clientX, event.clientY)
          }}
      >
        {value}
      </div>
    );
  }
}

ReactDOM.render(
    <Cell />,
    document.getElementById('init-cell')
);
.cell {
    background:grey;
    border-radius: 7px;
    border:0;
    transition: 0.25s;
    width:40px;
    height:25px;
    text-align: center;
    padding-top:5px;
}
.cell:hover {
    cursor: pointer;
    background:white;
}
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="change-param-window"></div>
<div id="init-cell"></div>

Upvotes: 0

Views: 68

Answers (1)

Matthew Brooks
Matthew Brooks

Reputation: 571

You almost certainly do not want to be using ReactDOM.render twice here. You should be rendering your app's root component with ReactDOM.render, but after that, if you want to render something outside the hierarchy of your component tree, you'll want to use React Portals. The docs here should sort you out. If you're still in need of help, I can dig deeper.

Upvotes: 1

Related Questions