React + Redux:将演示文稿与数据

时间:2016-10-30 01:35:43

标签: reactjs redux react-redux

我正在使用React& amp;终极版。我决定冒险进入Rechart& amp;终极版。我正在将事情分解为演示组件以及将处理数据的各自容器。尽管如此,我还是有些问题。这可能归结为我是如何做到的,我真的不确定。

现在我有SearchBarCurrentWeather和&我正在尝试将这些组件集成到Forecast组件和AppContainer中。到目前为止,我已将SearchBar组件集成到AppContainer中,并且它没有任何问题。这是我感到困惑的地方。所以我已经为容器提供了所需的操作和组件,并且容器已经connected,因此当用户进行搜索时,将进行api调用并且状态将通过reducer更新。

现在可以通过mapStateToProps提供这些数据吗?

如何在用户执行操作后使用该数据但是在初始渲染时不使用该数据?如果AppContainer正在呈现这三个组件,我显然会将道具传递给它们,以便它们按照预期进行渲染和运行。我认为这是可以使用生命周期的地方我只是不确定哪些或如何使用它们。我的代码AppContainerSearcBar和& CurrentWeather在下方。 CurrentWeather& Forecast几乎相同(仅为api的不同端点提供不同的数据),所以我没有提供。我也没有提供行动或减少因为我知道他们在我决定尝试这个重构之前工作正常。也许我需要一个以上的容器来解决这个问题?任何建议或指示都将非常感谢,感谢所有人,并有一个美好的夜晚。

**确实有一个附带问题:_weatherSearch event.preventDefault();我有SearchBar因为event是表单元素。我甚至需要提供这个吗?如果term不是通过的,那么event我认为没有。正在使用SearchBar,如下所示onSubmit={event => getWeather(event.target.value)}

的表单元素

import React, { Component } from 'react'; import { connect } from 'react-redux'; import { fetchCurrentWeather, fetchForecast } from '../actions/actions'; import SearchBar from '../components/SearchBar'; import CurrentWeather from '../components/CurrentWeather'; class AppContainer extends Component { _weatherSearch(term) { event.preventDefault(); // Here is where we go to fetch weather data. this.props.fetchCurrentWeather(term); this.props.fetchForecast(term); } render() { const getWeather = term => {this._weatherSearch(term);}; return ( <div className="application"> <SearchBar getWeather={getWeather}/> <CurrentWeather /> </div> ); } } const mapStateToProps = ({ current, forecast }) => { return { current, forecast } } export default connect(mapStateToProps, { fetchCurrentWeather, fetchForecast })(AppContainer);

App Container:

import React from 'react';

const SearchBar = ({ getWeather }) => {
  return(
    <form className='input-group' onSubmit={event => getWeather(event.target.value)}>
      <input
      className='form-control'
      placeholder='Search a US City' />
      <span className='input-group-btn'>
        <button className='btn btn-secondary' type='submit'>Submit</button>
      </span>
    </form>
  );
}

export default SearchBar;

搜索栏:

CurrentWeather

CurrentWeather:*注意:我还没有从import React, {Component} from 'react'; import {connect} from 'react-redux'; import {unitConverter} from '../conversions/conversions_2.0'; export class CurrentWeather extends Component { _renderCurrentWeather(cityData) { const name = cityData.name; const {temp, pressure, humidity} = cityData.main; const {speed, deg} = cityData.wind; const {sunrise, sunset} = cityData.sys; return ( <tr key={name}> <td>{unitConverter.toFarenheit(temp)} F</td> <td>{unitConverter.toInchesHG(pressure)}"</td> <td>{humidity}%</td> <td>{unitConverter.toMPH(speed)}mph {unitConverter.toCardinal(deg)}</td> </tr> ); } render() { let currentWeatherData = []; if (this.props.current) { currentWeatherData = this.props.current.map(this._renderCurrentWeather); } return ( <table className="table table-reflow"> <thead> <tr> <th>Temperature</th> <th>Pressure</th> <th>Humidity</th> <th>Wind</th> </tr> </thead> <tbody> {currentWeatherData} </tbody> </table> ); } } function mapStateToProps({current}) { return {current}; } export default connect(mapStateToProps)(CurrentWeather); 中删除任何逻辑或数据处理,所以它还没有被重构为仅有表示的组件。

RTCPeerConnection

2 个答案:

答案 0 :(得分:2)

您的渲染功能非常动态。你可以省略任何你喜欢的东西:

class AppContainer extends Component {

  _weatherSearch(term) {
    // event.preventDefault(); We can't do this because we don't have an event here...

    this.props.fetchCurrentWeather(term);
    this.props.fetchForecast(term);
    }

  render() {
    const getWeather = term => { this._weatherSearch(term); };
    return (
      <div className="application">
        <SearchBar getWeather={getWeather}/>
        { Boolean(this.props.current) && <CurrentWeather /> }
      </div>
    );
  }
}

const mapStateToProps = ({ current }) => ({ current });

export default connect(mapStateToProps,
  { fetchCurrentWeather, fetchForecast })(AppContainer);

这是您处理缺失数据的方式。你只需要显示任何内容,或者首先搜索一条消息,或者如果它正在加载,你就可以显示一个微调器或悸动者。

上面用来隐藏CurrentWeather的技术是,如果我们想要隐藏组件,则将布尔值传递给React。 React会忽略truefalsenullundefined

请注意,最好只在mapStateToProps中传递您实际将在组件内部使用的数据。在您的代码中,您传递了currentforecast,但您没有使用它们。

mapStateToPropsmapDispatchToPropsprops数据发生任何变化时,Redux将重新呈现。通过返回数据,您永远不会使用它指示Redux在没有必要时重新渲染。

答案 1 :(得分:2)

我自己就是反应 - 减少noob :-)而且我遇到过类似的问题。

据我所知,你所做的容器/表示分离看起来不错,但你可以更进一步,将容器的提取挂载

我所指的解决方案是人们不同地称之为“高阶组件”和“包装组件”:(以下代码未经过测试 - 仅用于说明目的)

import {connect} from blah;

const AppWrap = (Wrapped) => {
  class AppWrapper extends Component {
    constructor(props) {
      super(props);
      this.state = {foo: false};
    }
    componentWillMount() {
      this.props.actions.fooAction()
      .then(() => this.setState({foo: false}));
    }
    render() {
      return (<Wrapped {...this.props} foo={this.state.foo}/>);
    }
  }

  function mapState(state) { blah }
  function mapDispatch(dispatch) { blah }

  return connect(mapState, mapDispatch)(AppWrapper);
}

export default AppWrap;    

请注意顶部的= (Wrapped) => {部分。这就是正在进行实际的“包装”,只要你在渲染钩子中引用它就可以将参数命名为任何东西。

现在在你的AppContainer中,你得到一个this.props.foo,它作为一个标志告诉你fooAction()已经完成,你可以使用它来相应地呈现你的表现组件。在fooAction完成之前,您可以确保传入AppContainer的foofalse

要将我刚才所说的内容放入代码中,您的AppContainer可能看起来像这样:

import AppWrapper from './AppWrapper';

class AppContainer extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (!this.props.foo) ? <div>bar</div> : (
      <div blah>
        <SearchBar blah/>
        <CurrentWeather blah/>
      </div>
    );
  }
}

export default AppWrapper(AppContainer);

使用像这样的包装器组件的好处是

请查看此博客文章,了解有关HoC的更多信息:https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750