反应在一个子组件中更改状态并将其传递给另一个子组件

时间:2019-12-29 05:19:03

标签: reactjs

我有一个类似于Google字体页面的React应用。我正在使用Google字体API,它可以正常工作并正确显示所有字体。但是,有两件事我无法弄清楚。我有一个菜单,其中有一个文本输入字段和一个下拉字体大小菜单,并且有一个主要部分,每个google字体都有一张卡片,其中包含字体名称和一个显示字体外观的文本。文本输入字段中有一个默认文本,默认字体大小为40px。用户可以选择在输入字段中键入文本,更改默认文本以及更改字体大小。这两个都要求SearchMenu组件更改父组件中的值,并将新值更改为传递给CardList组件,然后再传递给CardList组件。但是,我传递文本字段和大小的方法不起作用,甚至我在构造函数中为它们设置的初始值也不起作用。这是我的代码:

app.js

import MainMenu from '../components/MainMenu.js';
import SearchMenu from '../components/SearchMenu.js';
import CardList from '../components/CardList.js';
import WebFont from 'webfontloader';

class App extends Component {
  constructor() {
    super()
    this.state = {
      fonts: [],
      searchfield: '',
      textfield: 'Text1',
      size: '40'
    }
  }

  componentDidMount(){
    fetch('https://www.googleapis.com/webfonts/v1/webfonts?key=AIzaSyA5GrPS2LztYbvuq-S38sx6CieY17p9FOY')
    .then(response=> response.json())
    .then(data=> this.setState({fonts: data.items}));

  }


  onSearchChange = (event) => {
    this.setState({searchfield: event.target.value })
  }

  onTextChange = (event) => {
    this.setState({textfield: event.target.value })
  }

  onSearchReset = () => {
    this.setState({searchfield: '' })
  }

  onFontSizeChange = (event) => {
    this.setState({size: event.target.value })
  }

  render () {
    const {fonts, searchfield, textfield, size} = this.state;
    const filteredFonts = fonts.filter(font => {
      return font.family.toLowerCase().includes(searchfield.toLowerCase());
      })

    return (
      <div className='tc'>
        <MainMenu />
        <SearchMenu searchChange={this.onSearchChange} textChange={this.onTextChange} sizeChange={this.onFontSizeChange}/>
        <CardList fonts={filteredFonts} textfield={textfield} size={size}/>
      </div>
    )
  }
}


export default App;

searchMenu.js

const SearchMenu = ({searchfield, searchChange, textfield, textChange, sizeChange, size}) => {
    return (
        <div className='center fixed bg-white w-100 dib mt5 pb5'>         
      <nav className="ma1 dib ba br-pill tc mw-90 center">        
        <input className="f6 black-80 bw0 dib ma2 .w5" 
          type='search' 
          placeholder='Search fonts'
          onChange={searchChange} />
        <input className="f6 black-80 b--silver dib ma2 .w5" 
          type='text' 
          placeholder='Type something'
          onChange={textChange} />
        <select id="Size" 
          className='pl2 pr2 bl mr3'
          onChange={sizeChange}>
            <option value="20">20px</option>
            <option value="24" >24px</option>
            <option value="32">32px</option>
            <option value="40" selected="selected">40px</option>
          </select>

      </nav>

        </div>
    );
}

export default SearchMenu;

CardList.js

import React from 'react';
import Card from './Card.js';

const CardList = ({fonts, textfield, size}) => {
    return (
        <div className='pv4 dib'> {
            fonts.map((user, i) => {
                return (<Card key={i} family={fonts[i].family}/>)
            })}
        </div>
    );
}

export default CardList;

Card.js

import React from 'react';
{/*import {Helmet} from "react-helmet";*/}
var WebFont = require('webfontloader');


const Card = ({family, textfield, size}) => {
    WebFont.load({
    google: {
      families: [`${family}`]
    }
  });

    const cardStyle = {
        fontFamily: family,
        fontSize: size
    };

    return (
        <div className='tl dib w-20 bt ma2 pa3'>
            <div>
                <h2 className='f6'>{family}</h2>
                <br />
                <p style={cardStyle}>{textfield}</p>
            </div>
        </div>      
    );
}

export default Card;

2 个答案:

答案 0 :(得分:0)

我看到的SearchMenu组件的一个问题是-输入字段未使用作为prop传递给它的textfield值。另外,app.js并未将文本字段值传递给SearchMenu组件。

SearchMenu组件应具有以下内容-

<input className="f6 black-80 b--silver dib ma2 .w5" 
      type='text' 
      placeholder='Type something'
      onChange={textChange} 
      value={textfield}/>

答案 1 :(得分:0)

您可以在props中发送对子组件的方法引用,这些方法可以更改父状态,并将该状态变量发送到props中的另一个子组件(例如兄弟组件)。

以下代码片段显示了如何在同级组件之间共享数据。完整的演示可以在here中找到。

class Parent extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      count1: 0,
      count2: 0,
    }
  }

  receiveDataFromChild(child,count){ 
      this.setState({[child]: count})
    }


  render() {
    return (
      <div>
        <h1>This is Parent. It's child1 is clicked {this.state.count1} times and child2 is clicked {this.state.count2} times</h1>

        <Child1 
            sendDataToParent={this.receiveDataFromChild.bind(this)} 
            count={this.state.count1} 
            brotherCount={this.state.count2}/>

        <Child2 
            sendDataToParent={this.receiveDataFromChild.bind(this)} 
            count={this.state.count2}
            brotherCount={this.state.count1}/>

      </div>
    );
  }
}

class Child1 extends React.Component {
  render(){
    return (
      <h2 onClick={()=>{this.props.sendDataToParent('count1', this.props.count+1)}}> This is Chiild1. My brother  is clicked {this.props.brotherCount} times </h2>
    )
  }
}

class Child2 extends React.Component {
  render(){
    return (
      <h2 onClick={()=>{this.props.sendDataToParent('count2', this.props.count+1)}}> This is Chiild2. My brother  is clicked {this.props.brotherCount} times </h2>
    )
  }
}