反应不将状态传播到子组件

时间:2016-11-17 01:25:17

标签: reactjs

我开始反应,我想出了以下问题。

下面的组件呈现了一个字体列表,这些字体是在我从"字体"导入。

为了显示字体,我使用了"消息"中指定的各种消息的数组。导入。

当我渲染列表时,renderFonts函数调用子组件" FontSample"并传递字体对象和消息以呈现为属性。

然后我得到了这个功能" addGreeting",它允许你设置一个特定的消息,在所有字体上显示它。我是通过将数组消息更改为只包含组件状态中的一条消息的数组来实现的。

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

我很确定这是我尚未学到的一些基本的反应行为,但我的好朋友谷歌已经回避了这一行为。

我很感激你的耐心,因为我是一名碰巧编码的设计师。

...正如建议的那样,使用示例编写代码: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(数组中的常规google 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;

编辑以包含有关该脚本的更多信息。

1 个答案:

答案 0 :(得分:2)

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

&#13;
&#13;
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>
        );
    }
}
&#13;
&#13;
&#13;

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

&#13;
&#13;
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>
        );
    }
}
&#13;
&#13;
&#13;

但是,在FontSample组件中,您根本不需要使用状态,您可以使用道具,然后每次新道具到达时都不需要设置状态

以下是codepen示例:http://codepen.io/magnetic/pen/GNNgvX?editors=0010

此处回答的类似问题:How can i keep state in a React component using ES6