2015-02-04 4 views
0

У меня есть список элементов. Когда я нажимаю значок «вверх» или «вниз», я хотел бы, чтобы список перестроился и, наконец, для приложения, чтобы перерегистрировать себя, чтобы я мог увидеть изменение, отраженное в DOM.Обновление состояния приложения при изменении дочернего компонента

Смена позиции списка работает. Я сталкиваюсь с проблемами при попытке запустить метод refreshState. Я передаю функцию как свойство дочернего элемента, но вызов этого свойства возвращает неопределенную функцию.

Вопрос: Как я могу назвать метод компонента из его дочернего компонента?

Код:

<!doctype html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>Test</title> 
    <script src="http://fb.me/react-with-addons-0.12.2.js"></script> 
    <script src="http://fb.me/JSXTransformer-0.12.2.js"></script> 
</head> 
<body> 
    <style> 
     /* CSS */ 
     span { 
      margin:0 0 0 10px; 
     } 
    </style> 
    <div id="app"></div> 
    <script type="text/jsx"> 
     // React 

     var _data = ['Red', 'Blue', 'Green']; 


     function getState() { 
      return { 
       colors: _data, 
      } 
     }; 


     Array.prototype.swap = function(a, b) { 
      var temp = this[a]; 
      this[a] = this[b]; 
      this[b] = temp; 
     }; 


     var App = React.createClass({ 

      getInitialState: function() { 
       return getState(); 
      }, 

      render: function() { 
       var colors = this.state.colors.map(function(color) { 
        return (
         <Color name={color} refreshState={this.refreshState} /> 
        ) 
       }); 
       return (
        <ul>{colors}</ul> 
       ) 
      }, 

      refreshState: function() { 
       return this.setState(getState()); 
      }, 

     }); 


     var Color = React.createClass({ 

      moveUp: function() { 
       var current = _data.indexOf(this.props.name), 
        above = current - 1; 

       if (above >= 0) { 
        _data.swap(current, above); 
       } 

       return this.props.refreshState(); 
      }, 

      moveDown: function() { 
       var current = _data.indexOf(this.props.name), 
        below = current + 1; 

       if (below < _data.length) { 
        _data.swap(current, below); 
       } 

       return this.props.refreshState(); 
      }, 

      render: function() { 
       return (
        <li> 
         <strong>{this.props.name}</strong> 
         <span onClick={this.moveUp}>^</span> 
         <span onClick={this.moveDown}>v</span> 
        </li> 
       ) 
      }, 

     }); 


     React.render(<App />, document.getElementById('app')); 
    </script> 
</body> 
</html> 

ответ

1

Заметили вы решили этот вопрос, но думал, что я упомяну, что вы можете передать простор .map, который не означает, что нет необходимости в кэш-области для описания:

this.state.colors.map(function(color) { 
    return (
     <Color 
      key={_data.indexOf(color)} 
      name={color} 
      refresh={this.refreshState} 
     /> 
    ) 
}, this); // pass the scope to .map 
+0

TIL. Это гораздо лучший ответ! Спасибо! –

0

Я пытался позвонить this.refreshState в рамках метода map. Это, конечно, не имеет такой же возможности, как метод render. Решение было сохранить объем в переменной:

var refresh = this.refreshState; 

Затем использовать эту переменную в методе map:

... refreshState={refresh} ... 

Всегда быть в курсе вашей сферы!

Если у вас есть несколько функций, которые не входят в локальную область, вы можете сохранить this в переменной.

var self = this; 
z.map(function(arg) { 
    x={self.refreshState} y={self.otherThing} 

И для любопытных, готового результата:

<!doctype html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>Test</title> 
    <script src="http://fb.me/react-with-addons-0.12.2.js"></script> 
    <script src="http://fb.me/JSXTransformer-0.12.2.js"></script> 
</head> 
<body> 
    <style> 
     /* CSS */ 
     span { 
      margin:0 0 0 10px; 
     } 
    </style> 
    <div id="app"></div> 
    <script type="text/jsx"> 
     // React 

     var _data = ['Red', 'Blue', 'Green']; 


     function getState() { 
      return { 
       colors: _data, 
      } 
     }; 


     Array.prototype.swap = function(a, b) { 
      var temp = this[a]; 
      this[a] = this[b]; 
      this[b] = temp; 
     }; 


     var App = React.createClass({ 

      getInitialState: function() { 
       return getState(); 
      }, 

      refreshState: function() { 
       return this.setState(getState()); 
      }, 

      render: function() { 
       var self = this; 
       var colors = this.state.colors.map(function(color) { 
        return (
         <Color 
          key={_data.indexOf(color)} 
          name={color} 
          refresh={self.refreshState} 
         /> 
        ) 
       }); 
       return (
        <ul>{colors}</ul> 
       ) 
      }, 

     }); 


     var Color = React.createClass({ 

      propTypes: { 
       name: React.PropTypes.string, 
       refresh: React.PropTypes.func.isRequired, 
      }, 

      moveUp: function() { 
       var current = _data.indexOf(this.props.name), 
        above = current - 1; 

       if (above >= 0) { 
        _data.swap(current, above); 
       } 

       return this.props.refresh(); 
      }, 

      moveDown: function() { 
       var current = _data.indexOf(this.props.name), 
        below = current + 1; 

       if (below < _data.length) { 
        _data.swap(current, below); 
       } 

       return this.props.refresh(); 
      }, 

      render: function() { 
       return (
        <li> 
         <strong>{this.props.name}</strong> 
         <span onClick={this.moveUp}>^</span> 
         <span onClick={this.moveDown}>v</span> 
        </li> 
       ) 
      }, 

     }); 


     React.render(<App />, document.getElementById('app')); 
    </script> 
</body> 
</html>