Child component in react prevents parent component from importing redux store

允我心安 提交于 2021-01-28 11:15:46

问题


I have two react components which work independently of each other but when connected seem to break the core of my program. My setup is this: Redux store --> MusicList.js(first component) --> AppNavbar.js(second component inside MusicList.js). Independently the redux store works perfectly with the first component, but when I connect my second component to MusicList.js it breaks the importation of my store. There is also a third component "Items.js" which is connected to MusicList.js in the same fashion as the second component, it also uses the redux store as a prop and yet it works perfectly fine without breaking the program.

Here is the code:

MusicList.js:

import React, {Component, useState } from "react";
import Items from "./Items";
import AddItem from "./AddItem";
import { connect } from "react-redux";
import { getItems, deleteItem, addItem, toggleItem } from "../actions/itemActions"
import PropTypes from "prop-types";
import AppNavbar from "./AppNavbar.js";

class MusicList extends Component {

    // Both componentWillMount and componentDidMount fail to get the items from my databse when the AppNavbar.js is connected. 
    // They both work when I comment out AppNavbar.js.
    // The setTimeout changes nothing.
    componentWillMount() {
        console.log("test")
        this.props.getItems();
        const func = () => {
            console.log(this.props.item)
        }
        setTimeout(func, 5000);
    }

    toggle = (id) => {
        this.props.toggleItem(id)
        console.log(this.props.item.items)
    }

    delItem = (id) => {
        this.props.deleteItem(id)
    }

    addItem = (item, url) => {
        this.props.addItem(item, url)
        console.log(this.props.item.items)
    }

    render() {
        
        const { items } = this.props.item
        console.log(items)

        return (
            
            <div>

                <div class="sticky-top">
                    // In this example the Appnavbar is commented out. 
                    // The program will get the items from the backend.
                    {/* <AppNavbar toggle={this.toggle} items={items}/> */}
                    <AddItem addItem={this.addItem}/>
                </div>

                <Items items={items} toggle={this.toggle} delItem={this.delItem} />

            </div>

        )
        
    }

}

MusicList.propTypes = {
    getItems: PropTypes.func.isRequired,
    deleteItem: PropTypes.func.isRequired, 
    addItem: PropTypes.func.isRequired,
    toggleItem: PropTypes.func.isRequired,
    item: PropTypes.object.isRequired
}

const mapStateToProps = (state) => ({
    item: state.item
})

export default connect(mapStateToProps, { getItems, deleteItem, addItem, toggleItem})(MusicList);

AppNavbar.js:

import React, { Component } from "react";
import {
    Navbar,
    NavbarBrand,
    Nav,
    Button
} from "react-bootstrap";
import './style.css';
import PropTypes from "prop-types";

class AppNavbar extends Component {

    playTrack = (track_index, items, placeholderTitle, isPlaying, isShuffling) => { 

        console.log(items)
        
        isPlaying = true;

        // playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
        
        // Load a new track
        if (isShuffling) {
            track_index = Math.floor(Math.random() * items.length)

            items[track_index].this.props.toggle()

            // this.props.toggle(trackIndexToID)

        }
        else {
            items[track_index].this.props.toggle()
        }
        
        // Update details of the track 
        placeholderTitle = this.props.items[track_index].name; 
        
        // Move to the next track if the current finishes playing 
        // using the 'ended' event 

        // items[track_index].addEventListener("ended", nextTrack); 

    }

    playpauseTrack = (track_index, isPlaying, items, placeholderTitle, isShuffling, playTrack, pauseTrack) => { 
        // Switch between playing and pausing 
        // depending on the current state 
        if (!isPlaying) playTrack(track_index, items, placeholderTitle, isPlaying, isShuffling); 
        else pauseTrack(track_index, items, placeholderTitle, isPlaying); 
    }

    pauseTrack = (track_index, items, placeholderTitle, isPlaying) => {

        // Pause the loaded track 
        
        isPlaying = false; 
        
        // Replace icon with the play icon 
        // playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';

        items[track_index].this.props.toggle()
    }
        
    nextTrack = (track_index, isLooping, items, playTrack) => { 
        // Go back to the first track if the 
        // current one is the last in the track list 
        if (track_index < items.length - 1 && !isLooping) {
            track_index += 1; 
        }
        else if (isLooping) {
            track_index = track_index
        }
        else track_index = 0; 
        
        // Load and play the new track 
        playTrack(track_index); 
    } 
        
    prevTrack = (track_index, isLooping, items, playTrack) => { 
        // Go back to the last track if the 
        // current one is the first in the track list 
        if (track_index > 0 && !isLooping) {
            track_index -= 1;
        }
        else if (isLooping) {
            track_index = track_index
        }
        else track_index = items.length; 
        // Load and play the new track 
        playTrack(track_index); 
    }


    // Connect to loop track icon
    loopTrack = (element, isLooping, isShuffling, loopOn, shuffleOff, LoopOff) => {
        if (!isLooping) {
            loopOn(element, isLooping);
            shuffleOff(element, isShuffling);
        }
        else LoopOff(element, isLooping);
    }

    // Connect to shuffle track icon
    shuffleTrack = (element, isLooping, isShuffling, shuffleOn, LoopOff, shuffleOff) => {
        if (!isShuffling) {
            shuffleOn(element, isShuffling);
            LoopOff(element, isLooping);
        }
        else shuffleOff(element, isShuffling);
    }

    loopOn = (element, isLooping) => {
        isLooping = true;
        element.style.opacity = "1"
        console.log("1" + isLooping)
    }

    LoopOff = (element, isLooping) => {
        isLooping = false;
        element.style.opacity = "0.8"
        console.log("2" + isLooping)
    }

    shuffleOn = (element, isShuffling) => {
        isShuffling = true;
        element.style.opacity = "1"
        console.log("3" + isShuffling)
    }

    shuffleOff = (element, isShuffling) => {
        isShuffling = false;
        element.style.opacity = "0.8"
        console.log("4" + isShuffling)
    }

    render() {

        console.log(this.props.items)
        var placeholderTitle = "Who asked (Feat: Nobody)";
        let track_index = 0;
        let isShuffling = false;
        let isLooping = false;
        let isPlaying = false;

        return (

            <Navbar className="Navbar">
                <NavbarBrand id="Logo" href="#home">
                    <img
                    alt=""
                    src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Logo-Smaller.png')}
                    />
                </NavbarBrand>
                <Navbar.Toggle aria-controls="basic-navbar-nav" />
                <Navbar.Collapse id="basic-navbar-nav">

                    <Nav className="mr-auto">

                        <ul className="navbar-nav">

                            <li>
                                <a href="#" className="Title">
                                    Embedded Music
                                </a>
                            </li>
                        
                        </ul>

                    </Nav>

                    <Nav className="mr-auto">

                    <div id="PlayerBox">

                        <ul className="navbar-nav">

                            <li>

                                <header id="Player">
                                    Now Playing:
                                </header>

                                <header id="Player">
                                    {placeholderTitle}
                                </header>

                                <img class="Previous transparent" id="Player" 
                                alt=""
                                onClick={this.prevTrack(track_index, isLooping, this.props.items, this.playTrack())}
                                src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Previous-smallest.png')}
                                />

                                <img class="playpauseTrack transparent" id="Player"
                                alt=""
                                onClick={this.playpauseTrack(track_index, isPlaying, this.props.items, placeholderTitle, isShuffling, this.playTrack(), this.pauseTrack())}
                                src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Play-smallest.png')}
                                />
                                
                                <img class="Next transparent" id="Player" 
                                alt=""
                                onClick={this.nextTrack(track_index, isLooping, this.props.items, this.playTrack())}
                                src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Next-smallest.png')}
                                />

                                <img class="Loop transparent" id="Player"
                                alt=""
                                onClick={this.loopTrack(this, isLooping, isShuffling, this.loopOn(), this.shuffleOff(), this.LoopOff())}
                                src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Loop-small.png')}
                                />

                                <img class="Shuffle transparent" id="Player" 
                                alt=""
                                onClick={this.shuffleTrack(this, isLooping, isShuffling, this.shuffleOn(), this.LoopOff(), this.shuffleOff())}
                                src={require('D:/Parrot/Desktop/Dev/Duplicate/Embedded_Music_Player/client/src/images/Shuffle-smallest.png')}
                                />

                            </li>

                        </ul>

                    </div>

                    </Nav>

                </Navbar.Collapse>
            </Navbar>
        )
    }
}

AppNavbar.propTypes = {
    toggle: PropTypes.func.isRequired,
    items: PropTypes.array.isRequired
}


export default AppNavbar;

Items.js:

import React, { Component } from 'react';
import Item from "./Item";
import PropTypes from "prop-types";

class Items extends Component {
    
    render() {

        return this.props.items.map((item) => (

            <div>

                <Item key={item._id} item={item} toggle={this.props.toggle} delItem={this.props.delItem} isOpen={item.isOpen}/>

            </div>

            ));
    }
}

// PropTypes
Items.propTypes = {
    items: PropTypes.array.isRequired
}

export default Items;

The second component is quite long but when I comment out any calls to "this.props.items" the program works and MusicList.js is capable of getting the items from the backend and logging them. If I dont comment out anything I get the error of "items is undefined" and my logs in MusicList.js show the items array as empty. My leading theory is that paradoxically the error in AppNavbar which shows items are undefined effectively seizes the entire program and MusicList never mounts, and because it never mounts it never gets the items and thus it can never give the items to AppNavbar and so the cycle repeats. I'm not sure if that makes much sense but It's the only thing I can clearly see. However there is still the question of the third component, it manages to load perfectly without error and does not seize up the program like I would expect if I follow the theory above. So I am quite confused as to what the problem is and any ideas would be greatly appreciated.

来源:https://stackoverflow.com/questions/64944530/child-component-in-react-prevents-parent-component-from-importing-redux-store

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!