简体   繁体   English

REDUX。我无法理解如何连接定义为扩展 React.Component 的 class 的组件以读取商店

[英]REDUX. I cant understand how to connect a component defined as a class extending React.Component in order to read the store

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.首先,我读过这个问题React-redux connect() cannot wrap component defined as a class extending React.Component但我仍然无法理解它,因为连接是在某种上层完成的,但我不明白那个阶段。

This is my current structure:这是我目前的结构:

reduxStore.js reduxStore.js

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

const store = createStore(rootReducer);

export default store;

action-types.js动作类型.js

export const RENDER_LAYOUT_ELEMENT = "REDER_LAYOUT_ELEMENT"

reduxActions.js reduxActions.js

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

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

reduxReducers.js 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 .现在我想要的是,读取我拥有的组件中的 renderedEl initialState 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)根据我的理解,我需要将该组件连接到商店,然后使用 mapStateToProps 它将读取全局 state(商店)

So i go to my component and try to connect it, but I dont understand where to do it.所以我 go 到我的组件并尝试连接它,但我不知道在哪里做。

The component is big, but basically Im trying to stop using the state of renderedEl, to read it from the store .该组件很大,但基本上我试图停止使用 renderedEl 的 state,以从商店读取它 The state im cur.netly using is located in the constructor, it should dissapear because it will now be read from the store. state im cur.netly using 位于构造函数中,它应该消失,因为它现在将从商店中读取。

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我看到的所有教程都与某种功能组件相关,而不是 class 组件

  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?我 go 如何连接该组件?

First you need to wrap a root component (most recommended index.js or App.js...) with redux Provider首先你需要用 redux Provider包装一个根组件(最推荐的 index.js 或 App.js ...)


  import { Provider } from 'react-redux'

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

After so, store is provided for all parts that under this, and can be connect ed like that如此之后,为所有在此之下的部分提供了存储,并且可以像那样connect


   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至于你的动作,将动作dispatch给减速器


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

do only export class SideBar [...] for testing purposes, but export default connect(mapStateToProps)(SideBar) which connects your component to redux state and assigns reduced state to props.仅出于测试目的export class SideBar [...] ,但export default connect(mapStateToProps)(SideBar) ,它将您的组件连接到redux state 并将减少的 state 分配给道具。

Edit: The documentation you're looking for is here .编辑:您要查找的文档位于此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM