te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Change component state on button click - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Change component state on button click - Stack Overflow

programmeradmin3浏览0评论

The following is the HTML.

<script src=".3284-6/12624079_897774290317920_1379776191_n.js"></script>
<script src=".3284-6/12624052_751451571621845_431133942_n.js"></script>


<script src=".8.24/browser.min.js"></script>

<div class="row" id="container">
  <div class="controls">
    <span class="" id="controls-size">Size : 
        <button id="controls-size-small">SMALL</button>
        <button id="controls-size-med">MEDIUM</button>
        <button id="controls-size-large">LARGE</button>
    </span>

  </div>
  <div id="game-container">
  </div>
</div>

The following is the Javscript

var SizeEnum = {
  SMALL: 1,
  MEDIUM: 2,
  LARGE: 3
};

var Board = React.createClass({
      getInitialState: function() {
        return {
          size: SizeEnum.MEDIUM
        };
      },

      ponentWillMount: function() {
        if (this.state.size == SizeEnum.SMALL) {
          this.style = {
            width: 600 + 'px',
            height: 320 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        } else if (this.state.size == SizeEnum.MEDIUM) {
          this.style = {
            width: 700 + 'px',
            height: 500 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        } else if (this.state.size == SizeEnum.LARGE) {
          this.style = {
            width: 900 + 'px',
            height: 720 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        }
      },

      render: function() {
          return ( < div style = {
            this.style
          } > < /div>
    )
  }

});

ReactDOM.render(<Board / > , document.getElementById("game-container"));

And some CSS

#game-container {
    position: relative;
    margin-top: 32px;
    border: 1px solid black;
    width: 100%;
}

What I want is that when the appropriate button is clicked, the Board ponent be resized to the appropriate size.

I've tried doing it like this

var board = ReactDOM.render(<Board />, document.getElementById("game-container"));

document.getElementById("controls-size-small").onclick = changeBoardSize;
document.getElementById("controls-size-med").onclick = changeBoardSize;
document.getElementById("controls-size-large").onclick = changeBoardSize;

function changeBoardSize(event) {
    var etid = event.target.id;
    console.log(etid);
    if (etid == "controls-size-small") {
        // method 1
        board.state.size = SizeEnum.SMALL;
    } else if (etid == "controls-size-med") {
        // method 2
        board.state.size = SizeEnum.MEDIUM;
        ReactDOM.render(<Board />, document.getElementById("game-container"));
    } else if (etid == "controls-size-small") {
        // method 3
        board.setState({size: SizeEnum.SMALL});
        ReactDOM.render(<Board />, document.getElementById("game-container"));
    }
}

But it doesn't work.

The following is the HTML.

<script src="https://fbcdn-dragon-a.akamaihd/hphotos-ak-xtp1/t39.3284-6/12624079_897774290317920_1379776191_n.js"></script>
<script src="https://fbcdn-dragon-a.akamaihd/hphotos-ak-xfp1/t39.3284-6/12624052_751451571621845_431133942_n.js"></script>


<script src="https://cdnjs.cloudflare./ajax/libs/babel-core/5.8.24/browser.min.js"></script>

<div class="row" id="container">
  <div class="controls">
    <span class="" id="controls-size">Size : 
        <button id="controls-size-small">SMALL</button>
        <button id="controls-size-med">MEDIUM</button>
        <button id="controls-size-large">LARGE</button>
    </span>

  </div>
  <div id="game-container">
  </div>
</div>

The following is the Javscript

var SizeEnum = {
  SMALL: 1,
  MEDIUM: 2,
  LARGE: 3
};

var Board = React.createClass({
      getInitialState: function() {
        return {
          size: SizeEnum.MEDIUM
        };
      },

      ponentWillMount: function() {
        if (this.state.size == SizeEnum.SMALL) {
          this.style = {
            width: 600 + 'px',
            height: 320 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        } else if (this.state.size == SizeEnum.MEDIUM) {
          this.style = {
            width: 700 + 'px',
            height: 500 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        } else if (this.state.size == SizeEnum.LARGE) {
          this.style = {
            width: 900 + 'px',
            height: 720 + 'px',
            margin: 'auto',
            border: '2px solid red'
          }
        }
      },

      render: function() {
          return ( < div style = {
            this.style
          } > < /div>
    )
  }

});

ReactDOM.render(<Board / > , document.getElementById("game-container"));

And some CSS

#game-container {
    position: relative;
    margin-top: 32px;
    border: 1px solid black;
    width: 100%;
}

What I want is that when the appropriate button is clicked, the Board ponent be resized to the appropriate size.

I've tried doing it like this

var board = ReactDOM.render(<Board />, document.getElementById("game-container"));

document.getElementById("controls-size-small").onclick = changeBoardSize;
document.getElementById("controls-size-med").onclick = changeBoardSize;
document.getElementById("controls-size-large").onclick = changeBoardSize;

function changeBoardSize(event) {
    var etid = event.target.id;
    console.log(etid);
    if (etid == "controls-size-small") {
        // method 1
        board.state.size = SizeEnum.SMALL;
    } else if (etid == "controls-size-med") {
        // method 2
        board.state.size = SizeEnum.MEDIUM;
        ReactDOM.render(<Board />, document.getElementById("game-container"));
    } else if (etid == "controls-size-small") {
        // method 3
        board.setState({size: SizeEnum.SMALL});
        ReactDOM.render(<Board />, document.getElementById("game-container"));
    }
}

But it doesn't work.

Share Improve this question edited Mar 23, 2016 at 16:30 dorado asked Mar 23, 2016 at 16:14 doradodorado 1,5251 gold badge16 silver badges38 bronze badges 5
  • 2 Why do you have html with buttons in it? React is ponent based and all "html" should be in JSX within a render function – erichardson30 Commented Mar 23, 2016 at 16:31
  • agree with the above, those buttons should be ponents, then this is pretty simple – omarjmh Commented Mar 23, 2016 at 16:34
  • Ok so I make the buttons ponents.. then? – dorado Commented Mar 23, 2016 at 16:35
  • @dorado after making buttons the ponents, you should be able to attach an onClick function to them which in that onClick can change the state – erichardson30 Commented Mar 23, 2016 at 16:37
  • so that onClick on the button will be able to change the sate of the board? – dorado Commented Mar 23, 2016 at 16:37
Add a ment  | 

4 Answers 4

Reset to default 4

You can't set the state of a React ponent like that. And the ponent should be responsible for setting its own state.

Inside your Board ponent, set up event listeners in ponentDidMount. The best solution would be to let the buttons be part of the React application, but that's beyond the scope of this question. So let's say that the buttons are not part of the React application, then do something like this:

var Board = React.createClass({
  ...
  ...
  ponentDidMount: function(){
    var that = this;
    document.getElementById("controls-size-small").addEventListener('click', that.changeBoardSize, false);
    document.getElementById("controls-size-med").addEventListener('click', that.changeBoardSize, false);
    document.getElementById("controls-size-large").addEventListener('click', that.changeBoardSize, false);
  }

  changeBoardSize: function(e){
    /* get the element id and do the enum things here */
    this.setState({
      size: newSize
    });
  }
  render: function(){
    ...
    ...
  }
});

Then just move all that ponentWillMount style stuff to the render function.

Update

Fiddle: https://jsfiddle/dannyjolie/r525ux66/

You are taking the wrong approach. The hardest part about react is "Thinking in React." If you want things to work properly, the notion of reaching into the DOM directly, like you are doing with document.getElementById, is off the table.

The simplest way for you to get started is to render your button inside the render function of your Board ponent. Then you can put a click handler inside the Board ponent to set the state.

This should get you started:

    handleClick: function (event) {
       this.setState({ size: SizeEnum.SMALL });
    },
    render: function() {
              return ( 
                  <div>
                      <div style = { this.style}></div>
                      <input type="button" onClick={this.handleClick}
                  </div>
              )
    }

Once you get this working, if you want to separate your button from your button, then you will want to look into using a Flux implementation to pass state from ponent to ponent.

You should not change state of React ponent directly. Use setState function instead. When you call setState React will re-render poment.

Add new function setSize to your Board poment:

    var Board = React.createClass({
        getInitialState: function() {
          return {
            size: SizeEnum.MEDIUM
         };
     },
     setSize: function(size) {
        this._setStyle(size);
        this.setState({size: size});
     },
     _setStyle: fiunction(size) {
        if (size == SizeEnum.SMALL) {
             this.style = {
               width: 600 + 'px',
               height: 320 + 'px',
               margin: 'auto',
               border: '2px solid red'
            }
        } else if (size == SizeEnum.MEDIUM) {
            this.style = {
              width: 700 + 'px',
              height: 500 + 'px',
              margin: 'auto',
              border: '2px solid red'
           }
        } else if (this.state.size == SizeEnum.LARGE) {
            this.style = {
              width: 900 + 'px',
              height: 720 + 'px',
              margin: 'auto',
              border: '2px solid red'
           }
       }
     },
     ponentWillMount: function() {
        this._setStyle(this.state.size);
     },
     // ................
     render: function() {
      return ( <div style={this.style}></div>)
     }
     });

     function changeBoardSize(event) {
         var etid = event.target.id;
         console.log(etid);
        if (etid == "controls-size-small") {
            board.setSize(SizeEnum.SMALL);
        } else if (etid == "controls-size-med") {
             board.setSize(SizeEnum.MEDIUM);
        } else if (etid == "controls-size-small") {
             board.setSize(SizeEnum.LARGE);
        }
      }

This is an anti pattern though this is the right way to achieve what you are looking for.

Since ReactDOM.render returns an instance of the ponent that is rendered, you can use that and update it's state.

    function changeBoardSize(event) {
        var etid = event.target.id;
        console.log(etid);
        if (etid == "controls-size-small") {      
            board.setState({size: SizeEnum.SMALL});
        } else if (etid == "controls-size-med") {
            board.setState({size: SizeEnum.MEDIUM});     
        } else if (etid == "controls-size-small") {
            board.setState({size: SizeEnum.LARGE});
        }
    }

The right way to do this, is to make buttons ponents of Board and attach event handlers on them eg :

var Board = React.createClass({
      getInitialState: function() {
        return {
          size: SizeEnum.MEDIUM
        };
      },
      render: function() {
        return (
        <div>
           <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.SMALL)}>Small</a>
           <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.MEDIUM)}>Medium</a>
           <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.LARGE)}>Large</a>
        </div>  
        )
      },

      onSizeChangeClick: function(size, event){
        event.preventDefault();
        this.setState({
          size: size
        });
      }
})
发布评论

评论列表(0)

  1. 暂无评论