React Redux help. Uncaught TypeError: Cannot read property 'reduxText' of undefined at mapStateToProps

Hi,

I am having trouble with undefined state in mapStateToProps in React Redux and I can’t put my finger on what the problem is. I have passed state into mapStateToProps, but if I then try to map a property of state to a property in mapStateToProps, it gives me “Uncaught TypeError: Cannot read property ‘reduxText’ of undefined at mapStateToProps”. However, if I use store.getState in mapStateToProps, it works perfectly, but I know I shouldn’t be doing this. Could anyone please advise on what I’m doing wrong here? I feel like there’s something crucial that I’m missing but I just can’t figure it out.

Thanks a lot! :slight_smile:

const quoteArr=[
  ['I destroy my enemies when I make them my friends', 'Abraham Lincoln'],
  ['Don’t live the same year 75 times and call it a life', 'Robin Sharma'],
  ['Genius is 1% inspiration, 99% perspiration', 'Thomas Edison'],
  ['Numbing the pain for a while will only make it worse when you finally feel it', 'Albus Dumbledore'],
  ['Instead of wondering when your next vacation is, maybe you should set up a life you don’t need to escape from', 'Seth Godin'],
  ['Spread love wherever you go. Let no one ever come to you without leaving happier', 'Mother Teresa'],
  ['When you reach the end of your rope, tie a knot in it and hang on', 'Franklin D. Roosevelt'],
  ['The only impossible journey is the one you never begin', 'Tony Robbins'],
  ['Do not let making a living prevent you from making a life', 'John Wooden'],
  ['It is better to fail in originality than to succeed in imitation', 'Herman Melville']
];

const colorArr=['blue', 'purple', 'pink', 'red', 'orange', 'yellow', 'green', 'cyan'];

let quoteRandomIndex=Math.floor(Math.random()*10);
let initialColorRandomIndex=Math.floor(Math.random()*8);
let colorRandomIndex=Math.floor(Math.random()*8); 

//Redux

  //Redux actions

const CHANGE_QUOTE_ACTION='CHANGE_QUOTE_ACTION';
const CHANGE_QUOTE_TRANSITION='CHANGE_QUOTE_TRANSITION';

  //Redux action creators

const changeQuoteActionCreator=()=>{
  return {
    type: CHANGE_QUOTE_ACTION,
    payload: {
      reduxText: quoteArr[quoteRandomIndex][0],
      reduxAuthor: quoteArr[quoteRandomIndex][1],
      reduxTweetURL: 'https://twitter.com/intent/tweet?text=\"'+quoteArr[quoteRandomIndex][0]+'\" '+quoteArr[quoteRandomIndex][1],
      reduxTextFade: 'textVisible '
    }
  } 
} 

const changeQuoteTransitionActionCreator=()=>{
  while(quoteArr[quoteRandomIndex][0]==store.getState().reduxText) { 
    quoteRandomIndex=Math.floor(Math.random()*10);
    }
  while('container-fluid '+colorArr[colorRandomIndex]+'-color'==store.getState().reduxBackgroundColor) {
    colorRandomIndex=Math.floor(Math.random()*8);
  };
  return {
    type: CHANGE_QUOTE_TRANSITION,
    payload: {
    reduxBackgroundColor: 'container-fluid '+colorArr[colorRandomIndex]+'-color',
    reduxButtonColor: 'btn btn-outline shadow-none text-white ' +colorArr[colorRandomIndex]+'-color '+colorArr[colorRandomIndex]+'-hoverColor',
    reduxTextColor: colorArr[colorRandomIndex]+'-textColor',
    reduxTextFade: 'textInvisible'
    }
  }
}

const asyncChangeQuoteActionCreator=()=>{
  return function(dispatch) {
    dispatch(changeQuoteTransitionActionCreator());
    setTimeout(function() {
      dispatch(changeQuoteActionCreator());
    }, 1000);
  };
}

//Initial Redux state

initialReduxState={
  reduxText: '',
  reduxAuthor: '',
  reduxBackgroundColor: 'container-fluid '+colorArr[initialColorRandomIndex]+'-color',
  reduxButtonColor: 'btn btn-outline shadow-none text-white ' +colorArr[initialColorRandomIndex]+'-color '+colorArr[initialColorRandomIndex]+'-hoverColor',
  reduxTextColor: colorArr[initialColorRandomIndex]+'-textColor',
  reduxTweetURL: ''
}

  //Redux reducer

const changeQuoteReducer=(state=initialReduxState, action)=>{
  console.log(state);
  switch (action.type) {
    case CHANGE_QUOTE_ACTION:
      return Object.assign({}, state, {reduxText: action.payload.reduxText, reduxAuthor: action.payload.reduxAuthor, reduxTweetURL: action.payload.reduxTweetURL, reduxTextFade: action.payload.reduxTextFade});
    case CHANGE_QUOTE_TRANSITION:
      return Object.assign({}, state, {reduxBackgroundColor: action.payload.reduxBackgroundColor, reduxButtonColor: action.payload.reduxButtonColor, reduxTextColor: action.payload.reduxTextColor, reduxTextFade: action.payload.reduxTextFade})
    default:
      return state;
  }
}

  //Redux store (including Thunk)

const store=Redux.createStore(
  changeQuoteReducer,
  Redux.applyMiddleware(ReduxThunk.default)
);

  //Redux Provider

const Provider=ReactRedux.Provider;

  //Redux connect

const connect=ReactRedux.connect;

//React

class Presentational extends React.Component {
  constructor(props) {
    super(props);
    this.changeQuote=this.changeQuote.bind(this);
  }
  changeQuote() {
    this.props.changeQuoteDispatch();  
   }
     componentDidMount() {
       setTimeout(()=>{
         this.props.changeQuoteDispatch(); 
       }, 500);
     } 
  render() {
  return ( 
    <div class={this.props.backgroundColor} id='background' style={{position: 'fixed', height: '100%'}}> 
      <div class='d-flex align-items-center justify-content-center' id='quote-box-flexbox-wrapper' style={{height: '100%'}}>  
        <div class={this.props.textColor} id='quote-box' style={{backgroundColor: 'white', width: '550px'}}> 
          <div class='d-flex flex-column' id='quote-box-content-flexbox-wrapper'>
            <TextComponent text={this.props.text} textFade={this.props.textFade}/>
            <AuthorComponent author={this.props.author} textFade={this.props.textFade}/>
            <div class='d-flex justify-content-between' id='buttons-flexbox-wrapper'>
              <NewQuoteComponent changeQuote={this.changeQuote} backgroundColor={this.props.backgroundColor} buttonColor={this.props.buttonColor}/>
              <TweetQuoteComponent tweetURL={this.props.tweetURL} buttonColor={this.props.buttonColor}/>
            </div>
          </div>
        </div>
      </div>
    </div>
    );  
  }
}  

class TextComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <p class={this.props.textFade} id='text' style={{textAlign: 'center', lineHeight: '1'}}><span class='quoteMark' style={{fontFamily: 'RocknRoll One'}}>“</span>{this.props.text}</p>
    );
  }
} 

class AuthorComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <p class={this.props.textFade} id='author'>{this.props.author}</p>
    );
  }
}

class NewQuoteComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
        <button type='button' class={this.props.buttonColor} id='new-quote' onClick={this.props.changeQuote}>New quote</button> 
    );
  }
}

class TweetQuoteComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <a href={this.props.tweetURL} class={this.props.buttonColor} id='tweet-quote' target='_top'><img src='https://i.imgur.com/dRBtqhv.png' style={{width: 30}}/></a> 
    );
  }
}

//Redux

  //Map state to props

const mapStateToProps=(state)=>{
  tempState=store.getState(); //Why do I have to do this?
  return {
    text: tempState.reduxText,
    author: tempState.author,
    backgroundColor: tempState.reduxBackgroundColor,
    buttonColor: tempState.reduxButtonColor,
    textColor: tempState.reduxTextColor,
    tweetURL: tempState.reduxTweetURL,
    textFade: tempState.reduxTextFade
  } 
} 

  //Map dispatch to props

const mapDispatchToProps=(dispatch)=>{
  return {
    changeQuoteDispatch: ()=>{
      dispatch(asyncChangeQuoteActionCreator())
    }
  }
}

  //Subscribe to the store

store.subscribe(mapStateToProps);

  //Dispatch to the store

store.dispatch(mapDispatchToProps);

  //Connect Redux to React

const Container=connect(mapStateToProps, mapDispatchToProps)(Presentational);

  //Redux Provider

class AppWrapper extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Container/> 
      </Provider>
    ); 
  }
}

ReactDOM.render(<AppWrapper/>, document.getElementById('random-quote-machine-node'));