2016-11-17 44 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

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