2016-11-17 43 views
0

我开始与反应,我想出了以下问题。反应不传播状态到子组件

下面的组件将呈现在我从“字体”导入中获得的数组中定义的字体列表。

要显示字体,我使用“消息”导入中指定的各种消息的数组。

当我渲染列表时,renderFonts函数调用一个子组件“FontSample”,并将字体对象和消息传递为属性。

然后我得到了这个函数“addGreeting”,它允许你设置一个特定的消息,以显示所有字体。我通过将数组消息更改为仅包含组件状态中的一条消息的数组来完成此操作。

问题是,虽然我可以验证状态正确更改,呈现器被触发,并且调用子组件,但呈现的字体列表中的消息根本不会改变。

我很确定这是一些基本的反应行为,我还没有学到,但我的好朋友谷歌一直在回避这一个。

您的耐心等级将会被赞赏,因为我是一位碰巧编码的设计师。

...而作为建议的,codepen与例如:http://codepen.io/davelinke/pen/YppzNW

import React, { Component } from 'react'; 

import FontSample from './FontSample'; 
import AddGreeter from './AddGreeter'; 
import Fonts from './Fonts'; 
import Messages from './Messages'; 

import './FontList.css'; 

class FontList extends Component { 
    constructor(props){ 
     super(props); 
     let theFonts = Fonts; 
     this.state = { 
      fonts:theFonts, 
      messages:Messages 
     }; 
     this.renderFonts = function(){ 
      let demMessages = this.state.messages; 
      let demFonts = this.state.fonts; 
      return demFonts.map((font,i) => (<FontSample key={i} font={font} message={demMessages[i % demMessages.length]} />)); 
     }.bind(this); 
     this.addGreeting = function(newName){ 
      console.log('hello ' + newName); 
      this.setState({ messages: [newName] }); 
     }.bind(this); 
    } 
    render() { 
     return (
      <div> 
       <AddGreeter addGreeting={this.addGreeting} /> 
       <div className="hello-world-list"> 
        {this.renderFonts()} 
       </div> 
      </div> 
     ); 
    } 
} 

export default FontList; 

Fonts.js(常规谷歌API JSON阵列内的数据)

let Fonts = [ 

    { 
     "kind": "webfonts#webfont", 
     "family": "Roboto", 
     "category": "sans-serif", 
     "variants": [ 
      "100", 
      "100italic", 
      "300", 
      "300italic", 
      "regular", 
      "italic", 
      "500", 
      "500italic", 
      "700", 
      "700italic", 
      "900", 
      "900italic" 
     ], 
     "subsets": [ 
      "greek-ext", 
      "latin-ext", 
      "latin", 
      "vietnamese", 
      "cyrillic-ext", 
      "cyrillic", 
      "greek" 
     ], 
     "version": "v15", 
     "lastModified": "2016-10-05", 
     "files": { 
      "100": "http://fonts.gstatic.com/s/roboto/v15/7MygqTe2zs9YkP0adA9QQQ.ttf", 
      "300": "http://fonts.gstatic.com/s/roboto/v15/dtpHsbgPEm2lVWciJZ0P-A.ttf", 
      "500": "http://fonts.gstatic.com/s/roboto/v15/Uxzkqj-MIMWle-XP2pDNAA.ttf", 
      "700": "http://fonts.gstatic.com/s/roboto/v15/bdHGHleUa-ndQCOrdpfxfw.ttf", 
      "900": "http://fonts.gstatic.com/s/roboto/v15/H1vB34nOKWXqzKotq25pcg.ttf", 
      "100italic": "http://fonts.gstatic.com/s/roboto/v15/T1xnudodhcgwXCmZQ490TPesZW2xOQ-xsNqO47m55DA.ttf", 
      "300italic": "http://fonts.gstatic.com/s/roboto/v15/iE8HhaRzdhPxC93dOdA056CWcynf_cDxXwCLxiixG1c.ttf", 
      "regular": "http://fonts.gstatic.com/s/roboto/v15/W5F8_SL0XFawnjxHGsZjJA.ttf", 
      "italic": "http://fonts.gstatic.com/s/roboto/v15/hcKoSgxdnKlbH5dlTwKbow.ttf", 
      "500italic": "http://fonts.gstatic.com/s/roboto/v15/daIfzbEw-lbjMyv4rMUUTqCWcynf_cDxXwCLxiixG1c.ttf", 
      "700italic": "http://fonts.gstatic.com/s/roboto/v15/owYYXKukxFDFjr0ZO8NXh6CWcynf_cDxXwCLxiixG1c.ttf", 
      "900italic": "http://fonts.gstatic.com/s/roboto/v15/b9PWBSMHrT2zM5FgUdtu0aCWcynf_cDxXwCLxiixG1c.ttf" 
     } 
    }, { 
     "kind": "webfonts#webfont", 
     "family": "Open Sans", 
     "category": "sans-serif", 
     "variants": [ 
      "300", 
      "300italic", 
      "regular", 
      "italic", 
      "600", 
      "600italic", 
      "700", 
      "700italic", 
      "800", 
      "800italic" 
     ], 
     "subsets": [ 
      "greek-ext", 
      "latin-ext", 
      "latin", 
      "vietnamese", 
      "cyrillic-ext", 
      "cyrillic", 
      "greek" 
     ], 
     "version": "v13", 
     "lastModified": "2016-10-05", 
     "files": { 
      "300": "http://fonts.gstatic.com/s/opensans/v13/DXI1ORHCpsQm3Vp6mXoaTS3USBnSvpkopQaUR-2r7iU.ttf", 
      "600": "http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSi3USBnSvpkopQaUR-2r7iU.ttf", 
      "700": "http://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzC3USBnSvpkopQaUR-2r7iU.ttf", 
      "800": "http://fonts.gstatic.com/s/opensans/v13/EInbV5DfGHOiMmvb1Xr-hi3USBnSvpkopQaUR-2r7iU.ttf", 
      "300italic": "http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxi9-WlPSxbfiI49GsXo3q0g.ttf", 
      "regular": "http://fonts.gstatic.com/s/opensans/v13/IgZJs4-7SA1XX_edsoXWog.ttf", 
      "italic": "http://fonts.gstatic.com/s/opensans/v13/O4NhV7_qs9r9seTo7fnsVKCWcynf_cDxXwCLxiixG1c.ttf", 
      "600italic": "http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxpZ7xm-Bj30Bj2KNdXDzSZg.ttf", 
      "700italic": "http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxne1Pd76Vl7zRpE7NLJQ7XU.ttf", 
      "800italic": "http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxg89PwPrYLaRFJ-HNCU9NbA.ttf" 
     } 
    } 
]; 
export default Fonts; 

Messages.js(一组消息)

let Messages = [ 
    'All their equipment and instruments are alive.', 
    'A red flair silhouetted the jagged edge of a wing.', 
    'I watched the storm, so beautiful yet terrific.', 
    'Almost before we knew it, we had left the ground.', 
    'A shining crescent far beneath the flying vessel.', 
    'It was going to be a lonely trip back.', 
    'Mist enveloped the ship three hours out from port.', 
    'My two natures had memory in common.', 
    'Silver mist suffused the deck of the ship.', 
    'The face of the moon was in shadow.', 
    'She stared through the window at the stars.', 
    'The recorded voice scratched in the speaker.', 
    'The sky was cloudless and of a deep dark blue.', 
    'The spectacle before us was indeed sublime.', 
    'Then came the night of the first falling star.', 
    'Waves flung themselves at the blue evening.' 
]; 

export default Messages; 

FontSample.js(字体样本组件)

import React, { Component } from 'react'; 
import './FontSample.css'; 
class FontSample extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      message: props.message, 
      style:{ 
       fontFamily:props.font.family 
      }, 
      fontName:props.font.family, 
      fontUrl:'https://fonts.googleapis.com/css?family='+props.font.family 
     }; 
    } 
    render() { 
     return (
      <div> 
       <link href={this.state.fontUrl} rel="stylesheet" type="text/css"></link> 
       <div className="font-wrapper"> 
        <div className="font-name">{this.state.fontName}</div> 
        <div className="font-sample" style={this.state.style}>{this.state.message}</div> 
       </div> 
      </div> 
     ); 
    } 
} 

export default FontSample; 

AddGreeter.js(保持所述UI更新消息的组件)

import React, { Component } from 'react'; 
import './AddGreeter.css'; 

class AddGreeter extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { greetingName: '' }; 
    this.handleUpdate = function(event) { 
     this.setState({ greetingName: event.target.value }); 
    }.bind(this); 
    this.addGreeting = function(){ 
     this.props.addGreeting(this.state.greetingName); 
     this.setState({ greetingName: '' }); 
    }.bind(this); 
    } 
    render() { 
    return (
     <div className="add-greeter"> 
     <input type="text" onChange={this.handleUpdate} value={this.state.greetingName}/> 
     &nbsp;&nbsp; 
     <button onClick={this.addGreeting}>Add</button> 
     </div> 
    ); 
    } 
} 

export default AddGreeter; 

被修改以包括有关所述脚本的详细信息。

+0

其余进口包含的内容是什么?即字体和消息? – Pineda

+0

添加了附加代码示例,感谢您的回复 –

+0

将它们(代码)贴到[CodePen](http://codepen.io/)并提供链接可以让您更快地获得答案。 :) –

回答

0

问题在于FontSample组件。你通过this.state.message显示你的消息。

class FontSample extends Component { 
 
    constructor(props) { 
 
     super(props); 
 
     this.state = { 
 
      message: props.message, 
 
      style:{ 
 
       fontFamily:props.font.family 
 
      }, 
 
      fontName:props.font.family, 
 
      fontUrl:'https://fonts.googleapis.com/css?family='+props.font.family 
 
     }; 
 
    } 
 
    render() { 
 
     return (
 
      <div> 
 
       <link href={this.state.fontUrl} rel="stylesheet" type="text/css"></link> 
 
       <div className="font-wrapper"> 
 
        <div className="font-name">{this.state.fontName}</div> 
 
        <div className="font-sample" style={this.state.style}>{this.state.message}</div> 
 
       </div> 
 
      </div> 
 
     ); 
 
    } 
 
}

这里,状态从道具设置一次,创建组件时,因为它是在构造函数中设置。当您的消息状态发生更改时,它将作为道具传递给FontSample,但FontSample的本地状态不会再次设置。为了设置FontSample的状态,您可以使用生命周期的方法componentWillRecieveProps,像这样:

class FontSample extends React.Component { 
 
    constructor(props) { 
 
     super(props); 
 
     console.log(props.message); 
 
     this.state = { 
 
      message: props.message, 
 
      style:{ 
 
       fontFamily:props.font.family 
 
      }, 
 
      fontName:props.font.family, 
 
      fontUrl:'https://fonts.googleapis.com/css?family='+props.font.family 
 
     }; 
 
    } 
 
    componentWillReceiveProps(newProps){ 
 
     this.setState({message: newProps.message}) 
 
    } 
 
    render() { 
 
     return (
 
      <div> 
 
       <link href={this.state.fontUrl} rel="stylesheet" type="text/css"></link> 
 
       <div className="font-wrapper"> 
 
        <div className="font-name">{this.state.fontName}</div> 
 
        <div className="font-sample" style={this.state.style}>{this.state.message}</div> 
 
       </div> 
 
      </div> 
 
     ); 
 
    } 
 
}

然而,在FontSample组件,您无需使用状态可言,你可以使用道具代替,那么就没有必要设置状态,每一次新道具到达

下面是codepen样本:http://codepen.io/magnetic/pen/GNNgvX?editors=0010

类似的问题在这里回答:How can i keep state in a React component using ES6

+0

布拉沃男人!非常感谢你。 –