Redux演示组件UI状态管理

时间:2018-07-08 23:50:02

标签: reactjs typescript redux react-redux

我有一个如下所述的容器和演示组件

Components
  |-Containers
    |- App.tsx
    |- ServiceContainer.tsx
  |-Presentation
    |-ServiceList.tsx
    |-ServiceListItem.tsx

问题:我已经阅读过演示容器不应具有任何状态,而只能从props渲染数据,而且传递的props不能映射到本地状态-很好,但是我需要在 ServiceListItem上悬停状态。悬停时,我需要显示服务的描述。如何在不在演示文稿组件上创建本地状态的情况下执行此操作?我是否需要为演示组件创建动作和缩减器?

这是我的密码。我有安装商店,减速器和操作器。

App.tsx

import * as React from "react";
import ServicesContainer from "./containers/ServicesContainer";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { IStateProps, IDispatchProps, ServiceListProps } from "../types/services/serviceModel";
import ServiceActionCreators from "../actions/serviceRecordActions";


class App extends React.Component<ServiceListProps>{

  constructor(props){
    super(props)
  }

  render(){
    return(
      <ServicesContainer {...this.props}/>
    )
  }
}


function mapStateToProps(state:any): IStateProps{
  return {services: state.serviceRecords}
}

function mapDispatchToProps(dispatch:any): IDispatchProps{

  const dispatchProps : any = {
      fetchServiceRecords : ServiceActionCreators.fetchServiceRecords,
      addServiceRecord: ServiceActionCreators.addServiceRecord,
      removeServiceRecord: ServiceActionCreators.removeServiceRecord
  }

  return bindActionCreators(dispatchProps, dispatch);

}

ServiceContainer.tsx

import * as React from "react";
import ServiceList from "../presentations/ServiceList";
import { ServiceListProps } from "../../types/services/serviceModel";


const ServicesContainer = (props: ServiceListProps) => {
    return (
        <ServiceList {...this.props}/>
    );
}

export default ServicesContainer;

ServiceList.tsx

import * as React from "react";
import { ServiceListProps} from "../../types/services/serviceModel";
import ServiceListItem from "../presentations/ServiceListItem";

// Stateless Component
class ServiceList extends React.Component<ServiceListProps> {

    constructor(props){
        super(props);
    }

    render(){
        return (
            <ul>
                {
                    this.props.services.map((s) => (
                        <ServiceListItem 
                            key={s.service.Id}
                            service={s.service}
                        />
                    ))
                }
            </ul>
        )
    }
}


export default ServiceList;

ServiceListItem.tsx

import * as React from "react";
import {ServiceListItemModel} from "../../types/services/serviceModel";

// Stateless Component

const ServiceListItem = (props:ServiceListItemModel) => {
    return(
        <li>

            {props.service.Name} 

            <a href="#" >Remove</a>
            // On Hover, I want to show this <p> tag
            <p > - {props.service.Description}</p> 

        </li>
    )
}

export default ServiceListItem;

更新(带有解决方案) 这按预期工作。没有道具可以显示状态图,仅显示道具数据

class ServiceListItem extends React.Component<ServiceListItemProps, any> {

    constructor(props){
        super(props);

        // only UI state changes
        this.state = {showDescription: false}
    }

    toggleDescription(){
        this.setState(prevState => ({showDescription: !prevState.showDescription}))
    }

    render(){
        return(
            <li 
                onMouseOver={() => this.toggleDescription()} 
                onMouseLeave={() => this.toggleDescription()}
                >

                {this.props.service.Name} 

                <a href="#" >Remove</a>

                {this.state.showDescription &&
                    <p > - {this.props.service.Description}</p> 
                }

            </li>
        )
    }

}

2 个答案:

答案 0 :(得分:1)

的确,表示组件不应具有状态,但是这里的状态纯粹是指从云或某些IO获取的数据驱动状态。这种状态需要在容器组件中处理。

由丹·阿布拉莫夫(Dan Abramov)在他的article中引用:

  
      
  • 修饰性成分与事物的外观有关。
  •   
  • 很少有自己的状态(当有状态时,它是UI状态而不是数据状态)。
  •   

在呈示形式的ServiceListItem组件中,具有本地状态将非常好,该状态将控制悬停行为,因为它是仍然不知道数据驱动状态的UI构造。

答案 1 :(得分:0)

您可以使用on hover事件并将状态设置回如下所示的容器状态

ServiceList.tsx

// Stateless Component
class ServiceList extends React.Component<ServiceListProps> {

    constructor(props){
        super(props);
        this.state = {hover: false};
    }

   //note here
   onHover(status: boolean) {
     this.setState({hover: status});
   }


    render(){
        return (
            <ul>
                {
                    this.props.services.map((s) => (
                        <ServiceListItem 
                            key={s.service.Id}
                            service={s.service}
                            hover={this.state.hover}
                            onHandleHoverEvent={this.onHover}
                        />
                    ))
                }
            </ul>
        )
    }
}


export default ServiceList;

然后

// Stateless Component

const ServiceListItem = (props:ServiceListItemModel) => {
    return(
        <li onMouseOver={() => this.props.onHandleHoverEvent(true)} onMouseOut={() => this.props.onHandleHoverEvent(false)}>

            {props.service.Name} 

            <a href="#" >Remove</a>
            { props.hover &&
               <p> - {props.service.Description}</p>
             }

        </li>
    )
}

export default ServiceListItem;