还原.我无法理解如何连接定义为扩展 React.Component 的类的组件以读取商店 [英] REDUX. I cant understand how to connect a component defined as a class extending React.Component in order to read the store

查看:41
本文介绍了还原.我无法理解如何连接定义为扩展 React.Component 的类的组件以读取商店的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我阅读了这个问题React-redux connect()不能包装定义为扩展 React.Component 的类的组件但是我仍然无法理解它,因为连接是在某种上层完成的,但我不明白那个阶段.

这是我目前的结构:

reduxStore.js

import { createStore } from "redux";从../reducers/index"导入rootReducer;const store = createStore(rootReducer);导出默认商店;

action-types.js

export const RENDER_LAYOUT_ELEMENT = "REDER_LAYOUT_ELEMENT"

reduxActions.js

从../constants/action-types"导入{RENDER_LAYOUT_ELEMENT}导出函数 renderLayoutElement(payload){返回{类型:RENDER_LAYOUT_ELEMENT}};

reduxReducers.js

从../constants/action-types"导入{RENDER_LAYOUT_ELEMENT}常量初始状态 = {渲染El:{海姆达尔:假的,斯卡迪:假的,墨卡托:假}}函数 renderElReducer(state = initialState, action){if(action.type === RENDER_LAYOUT_ELEMENT){返回 Object.assign({},state,{renderEl: state.renderedEl.concat(action.payload)})}返回状态}导出默认的 renderElReducer;

现在我想要是,读取我拥有的组件中的renderEl initialState.根据我的理解,我需要将该组件连接到商店,然后使用 mapStateToProps 它将读取全局状态(商店)

所以我转到我的组件并尝试连接它,但我不知道在哪里做.

组件很大,但基本上我试图停止使用renderEl的状态,从商店读取它.我当前使用的状态位于构造函数中,它应该消失,因为它现在将从存储中读取.

并且在渲染中,样式的条件部分现在不会根据状态设置,而是根据商店设置.我打算做所有这些,但问题是,对现在我坚持如何将此组件连接到商店.我看过的所有教程都与某种功能组件相关,而不是类组件

 import React, { Component, useState } from "react";从../images/valhallaNaranja.png"导入品牌;从@fortawesome/react-fontawesome"导入 { FontAwesomeIcon }从@fortawesome/free-regular-svg-icons"导入 { faArrowAltCircleLeft, faArrowAltCircleRight, faUser }从@fortawesome/free-solid-svg-icons"导入 { faColumns }导入'./css/Sidebar.css'从../services/userCheck.js"导入 { isAdmin }//选择const mapStateToProps = state =>{返回 { renderEl: state.renderedEl }}导出默认类 SideBar 扩展组件 {构造函数(道具){超级(道具);this.state = {收回:this.props.retracted,isAdmin:假,isHovering:假,//这个状态是我试图通过从商店阅读来替代的渲染El:{海姆达尔:假的,斯卡迪:假的,墨卡托:假}}this.hoverTrue = this.hoverTrue.bind(this);this.hoverFalse = this.hoverFalse.bind(this);}componentDidMount() {如果(isAdmin()){this.setState({isAdmin: 真})}}componentDidUpdate() {如果(this.state.retracted != this.props.retracted){this.setState({收回:this.props.retracted})}}renderEl = (el) =>{var elementName = el.target.getAttribute('id');var renderElements = this.state.renderedEl;for (let key in renderElements) {if (key == elementName) {renderElements[key] = true}}this.setState({renderEl: 渲染元素})}悬停真(){this.setState({isHovering: 真})}悬停假(){this.setState({isHovering: 假})}使成为() {让 navbar_brand = this.state.retracted ?"navbar-brand-retracted" : "navbar-brand";让 img_redie = this.state.retracted ?"img-redie-retracted" : "img-redie";让 home_icon = this.state.retracted ?"divicon homeicon-retracted" : "divicon homeicon";让 register_icon = this.state.retracted ?"divicon divicon2 registericon-retracted": "divicon divicon2 registericon";让 expand_icon = this.state.retracted ?"divicon-no-hover divicon2 expandicon-retracted": "divicon divicon2 expandicon";//现在将从商店中读取这些状态让 skadiRendered = this.state.renderedEl.skadi ?"bubbletext bubbletext-rendered": "bubbletext";让 heimdallRendered = this.state.renderedEl.heimdall ?"bubbletext bubbletext-rendered": "bubbletext";让 mercatorRendered = this.state.renderedEl.mercator ?"bubbletext bubbletext-rendered": "bubbletext";让 layoutAppVisualSelector = this.props.history.location.pathname == "/layout" ?"divicon divicon2 expandicon divicon-layout": "divicon divicon2 expandicon";返回 (<div id="sidebar" className={this.state.retracted ?'sidebar-retracted' : 'sidebar-expanded'}><div/*routerLink=""*/className={navbar_brand}><img alt="Reddie" src={brand} width="60" height="60" className={img_redie}/>

<ul className="nav nav3 navbar-nav"><li>{/* 主页图标 */}<div className={home_icon} onClick={() =>this.props.history.push('/')}><svg className="svgicon-sidebar" viewBox="0 0 14 14" ><路径d="M13.9 5.7L7.2.8c-.1-.1-.3-.1-.4 0L.1 5.7c-.1.1-.1.3 0 .5s.3.2.5.1L7 1.6l6.4 4.7c.1 0 .1.1.2.1s.2-.1.3-.1c.1-.3.1-.5 0-.6"/><路径d="M12.1 6.4c-.2 0-.4.2-.4.4v5.8H8.8V9.4c0-1-.8-1.8-1.8-1.8s-1.8.8-1.8 1.8v3.2H2.3V6.7c0-.2-.2-.4-.4-.4s-.4.2-.4.4v6.2c0 .2.2.4.4.4h3.6c.2 0 .3-.1.4-.3V9.4c0-.6.5-1.1 1.1-1.1.6 0 1.1.5 1.1 1.1v3.5c0 .2.2.3.4.3h3.6c.2 0 .4-.2.4-.4V6.7c0-.2-.2-.3-.4-.3"/></svg>

{this.state.isAdmin ?<li><div className={register_icon} onClick={() =>this.props.history.push('/admin')}><FontAwesomeIcon className="registerIcon" icon={faUser}/>

: 空值}{(this.props.history.location.pathname != "/layout") &&(this.props.history.location.pathname != "/skadi") &&(this.props.history.location.pathname != "/heimdall") &&(this.props.history.location.pathname != "/mercator") ?空:<li><div className={layoutAppVisualSelector} onMouseEnter={this.hoverTrue}onMouseLeave={this.hoverFalse} ><FontAwesomeIcon className="registerIcon" icon={faColumns} onClick={() =>this.props.history.push({ pathname: '/layout', state: { comeFrom: this.props.history.location.pathname } })}/>{(this.state.isHovering && this.props.history.location.pathname == "/layout") ?<div className="speech-bubble" onMouseLeave={this.hoverFalse}onMouseEnter={this.hoverTrue}><span id="heimdall" className={heimdallRendered} onClick={(el) =>this.renderEl(el)}>Heimdall</span><br/><span className={skadiRendered} id="skadi" onClick={(el) =>this.renderEl(el)}>Skadi</span><br/><span id="mercator" className={mercatorRendered} onClick={(el) =>this.renderEl(el)}>墨卡托</span>

: 空值}

</li>}{(this.state.retracted) ||((this.props.history.location.pathname == "/") || (this.props.history.location.pathname == "/register")) ||(this.props.history.location.pathname == "/admin") ||(this.props.history.location.pathname == "/layout") ?空:<li><div className="divicon divicon2 expandicon " onClick={this.props.retract}><FontAwesomeIcon className="registerIcon" icon={faArrowAltCircleLeft}/>

</li>}{this.state.retracted ?<div className="expandicon-retracted-container"><FontAwesomeIcon className="expandicon-retracted" icon={faArrowAltCircleRight} onClick={this.props.unretract}/>

: 空值}

)}}

我将如何连接该组件?

解决方案

首先你需要用 redux Provider

<小时>

 import { Provider } from 'react-redux'<提供者商店={商店}><应用程序/></提供者>

<小时>

这样之后,就为这个下的所​​有部分提供了存储,并且可以像那样connect

<小时>

 import { connect } from 'react-redux'const mapStateToProps = state =>{返回 { renderEl: state.renderedEl }}类 SideBar 扩展组件 {componentDidMount() {控制台日志(this.props.renderedEL)}}导出默认连接(mapStateToProps)(SideBar)

<小时>

至于你的动作,dispatch对reducer的动作

<小时>

导出函数renderLayoutElement(payload){返回调度 =>调度({类型:RENDER_LAYOUT_ELEMENT})}

<小时>

First of all, ive read this question React-redux connect() cannot wrap component defined as a class extending React.Component But im still unable to uderstand it since the connect is being done in some kind of upper level, but I dont understand that phase.

This is my current structure:

reduxStore.js

import { createStore } from "redux";
import rootReducer from "../reducers/index";

const store = createStore(rootReducer);

export default store;

action-types.js

export const RENDER_LAYOUT_ELEMENT = "REDER_LAYOUT_ELEMENT"

reduxActions.js

import {RENDER_LAYOUT_ELEMENT} from "../constants/action-types"

export function renderLayoutElement(payload){
    return {type: RENDER_LAYOUT_ELEMENT}
};

reduxReducers.js

import {RENDER_LAYOUT_ELEMENT} from "../constants/action-types"

const initialState = {
    renderedEl: {
        heimdall: false,
        skadi: false,
        mercator: false
    }
}

function renderedElReducer(state = initialState, action){
    if(action.type === RENDER_LAYOUT_ELEMENT){
        return Object.assign({},state,{
            renderedEl: state.renderedEl.concat(action.payload)
        })
    }
    return state
}

export default renderedElReducer;

Now what I want is, to read the renderedEl initialState in a component that I have. Per my understanding, i need to connect that component, to the store and then with a mapStateToProps it would read the global state (the store)

So i go to my component and try to connect it, but I dont understand where to do it.

The component is big, but basically Im trying to stop using the state of renderedEl, to read it from the store. The state im currnetly using is located in the constructor, it should dissapear because it will now be read from the store.

And in the render, the conditional parts of the style, now wont be set based on the states, but based on the store. I was going to do all that, but problem is, right now im stuck with how to connect this component to the store. All the tutorials I have seen are connected with some sort of functioncal componentes and not class componentes

  import React, { Component, useState } from "react";
import brand from "../images/valhallaNaranja.png";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import { faArrowAltCircleLeft, faArrowAltCircleRight, faUser } from '@fortawesome/free-regular-svg-icons'
import { faColumns } from '@fortawesome/free-solid-svg-icons'
import './css/Sidebar.css'
import { isAdmin } from "../services/userCheck.js"

//select
const mapStateToProps = state => {
    return { renderedEl: state.renderedEl }
}

export default class SideBar extends Component {
    constructor(props) {
        super(props);
        this.state = {
            retracted: this.props.retracted,
            isAdmin: false,
            isHovering: false,
            //THIS STATE IS WHAT IM TRYING TO REPLACE BY READING FROM THE STORE
            renderedEl: {
                heimdall: false,
                skadi: false,
                mercator: false
            }
        }

        this.hoverTrue = this.hoverTrue.bind(this);
        this.hoverFalse = this.hoverFalse.bind(this);
    }



    componentDidMount() {
        if (isAdmin()) {
            this.setState({
                isAdmin: true
            })
        }
    }

    componentDidUpdate() {
        if (this.state.retracted != this.props.retracted) {
            this.setState({
                retracted: this.props.retracted
            })
        }
    }

    renderEl = (el) => {
        var elementName = el.target.getAttribute('id');
        var renderedElements = this.state.renderedEl;

        for (let key in renderedElements) {
            if (key == elementName) {
                renderedElements[key] = true
            }
        }
        this.setState({
            renderEl: renderedElements
        })
    }

    hoverTrue() {
        this.setState({
            isHovering: true
        })
    }

    hoverFalse() {
        this.setState({
            isHovering: false
        })
    }

    render() {

        let navbar_brand = this.state.retracted ? "navbar-brand-retracted" : "navbar-brand";
        let img_redie = this.state.retracted ? "img-redie-retracted" : "img-redie";
        let home_icon = this.state.retracted ? "divicon homeicon-retracted" : "divicon homeicon";
        let register_icon = this.state.retracted ? "divicon divicon2 registericon-retracted" : "divicon divicon2 registericon";
        let expand_icon = this.state.retracted ? "divicon-no-hover divicon2 expandicon-retracted" : "divicon divicon2 expandicon";

    //THOSE STATES WILL BE READ NOW FROM THE STORE
        let skadiRendered = this.state.renderedEl.skadi ? "bubbletext bubbletext-rendered" : "bubbletext";
        let heimdallRendered = this.state.renderedEl.heimdall ? "bubbletext bubbletext-rendered" : "bubbletext";
        let mercatorRendered = this.state.renderedEl.mercator ? "bubbletext bubbletext-rendered" : "bubbletext";

        let layoutAppVisualSelector = this.props.history.location.pathname == "/layout" ? "divicon divicon2 expandicon divicon-layout" : "divicon divicon2 expandicon";
        return (
            <div id="sidebar" className={this.state.retracted ? 'sidebar-retracted' : 'sidebar-expanded'}>
                <div /*routerLink=""*/ className={navbar_brand}>
                    <img alt="Reddie" src={brand} width="60" height="60" className={img_redie} />
                </div>

                <ul className="nav nav3 navbar-nav">
                    <li>
                        {/* Home icon */}
                        <div className={home_icon} onClick={() => this.props.history.push('/')}>
                            <svg className="svgicon-sidebar" viewBox="0 0 14 14" >
                                <path d="M13.9 5.7L7.2.8c-.1-.1-.3-.1-.4 0L.1 5.7c-.1.1-.1.3 0 .5s.3.2.5.1L7 1.6l6.4 4.7c.1 0 .1.1.2.1s.2-.1.3-.1c.1-.3.1-.5 0-.6" />
                                <path d="M12.1 6.4c-.2 0-.4.2-.4.4v5.8H8.8V9.4c0-1-.8-1.8-1.8-1.8s-1.8.8-1.8 1.8v3.2H2.3V6.7c0-.2-.2-.4-.4-.4s-.4.2-.4.4v6.2c0 .2.2.4.4.4h3.6c.2 0 .3-.1.4-.3V9.4c0-.6.5-1.1 1.1-1.1.6 0 1.1.5 1.1 1.1v3.5c0 .2.2.3.4.3h3.6c.2 0 .4-.2.4-.4V6.7c0-.2-.2-.3-.4-.3" />
                            </svg>
                        </div>
                    </li>

                    {this.state.isAdmin ? <li>
                        <div className={register_icon} onClick={() => this.props.history.push('/admin')}>
                            <FontAwesomeIcon className="registerIcon" icon={faUser} />
                        </div>
                    </li> : null}


                    {(this.props.history.location.pathname != "/layout") && (this.props.history.location.pathname != "/skadi") && (this.props.history.location.pathname != "/heimdall") && (this.props.history.location.pathname != "/mercator") ? null : <li>
                        <div className={layoutAppVisualSelector} onMouseEnter={this.hoverTrue}
                            onMouseLeave={this.hoverFalse} >
                            <FontAwesomeIcon className="registerIcon" icon={faColumns} onClick={() => this.props.history.push({ pathname: '/layout', state: { comeFrom: this.props.history.location.pathname } })} />
                            {(this.state.isHovering && this.props.history.location.pathname == "/layout") ? <div className="speech-bubble" onMouseLeave={this.hoverFalse}
                                onMouseEnter={this.hoverTrue}>
                                <span id="heimdall" className={heimdallRendered} onClick={(el) => this.renderEl(el)}>Heimdall</span> <br /> <span className={skadiRendered} id="skadi" onClick={(el) => this.renderEl(el)}>Skadi</span> <br /> <span id="mercator" className={mercatorRendered} onClick={(el) => this.renderEl(el)}>Mercator</span>
                            </div> : null}

                        </div>

                    </li>}

                    {(this.state.retracted) || ((this.props.history.location.pathname == "/") || (this.props.history.location.pathname == "/register")) || (this.props.history.location.pathname == "/admin") || (this.props.history.location.pathname == "/layout") ? null : <li>
                        <div className="divicon divicon2 expandicon " onClick={this.props.retract}>
                            <FontAwesomeIcon className="registerIcon" icon={faArrowAltCircleLeft} />
                        </div>
                    </li>}



                </ul>

                {this.state.retracted ? <div className="expandicon-retracted-container"> <FontAwesomeIcon className="expandicon-retracted" icon={faArrowAltCircleRight} onClick={this.props.unretract} /> </div> : null}

            </div>

        )
    }
}

How would I go about connecting that component?

解决方案

First you need to wrap a root component (most recommended index.js or App.js...) with redux Provider


  import { Provider } from 'react-redux'

 <Provider store={store}>
    <App />
</Provider>


After so, store is provided for all parts that under this , and can be connected like that


   import { connect } from 'react-redux'

   const mapStateToProps = state => {
    return { renderedEl: state.renderedEl }
   }

  class SideBar extends Component {
      componentDidMount() {
         console.log(this.props.renderedEL)
     }
   }

 export default connect(mapStateToProps)(SideBar)


As for your action, dispatch the action towards the reducer


export function renderLayoutElement(payload){
   return dispatch => dispatch({type: RENDER_LAYOUT_ELEMENT})
 }


这篇关于还原.我无法理解如何连接定义为扩展 React.Component 的类的组件以读取商店的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆