Can't figure out if I implemented Redux correctly

Hello community! I am currently working on the markdown editor project for the following course:

Markdown Editor Project Descriptione

I posted and asked for help on the sites forums, and have not gotten a response for multiple days, so I hope it is okay to ask here. I have all the basics of the project functioning (according to their tests they provide). I think I am starting to understand React more, but I am still struggling with Redux. I reviewed the material on React and Redux section of the course while attempting to implement it into my project. However, I have the strong suspicion that I did not add it in properly because the Redux itself doesn’t feel like it is doing anything significant. I could be wrong, but I wanted to check first before proceeding with SCSS. I am currently using vite to create my applications. The following below is the file in question (App.jsx):

import React from 'react';
import {Provider, connect} from 'react-redux';
import {createStore} from 'redux';
import {marked} from "https://cdnjs.cloudflare.com/ajax/libs/marked/13.0.2/lib/marked.esm.js";

const CODE_CHANGED = 'CODE CHANGED';
const defaultCode = "# This is the first header!\n" + 
      "## This is the second header!\n" +
      "You can create links with markdown such as this one to YouTube [Click Me!](https://www.youtube.com)\n" +
      "This is how a line of code is made: `console.log(\'hello world\')`.\n" +
      "The following is an inline code block:\n" +
      "```\nfunction showcase() {\n" +
      "    console.log(\'This is a function!\');\n" +
      "}\n```\n\n\n" +
      "You can create blockquotes like this: \n> Here is a blockquote\n\n" +
      "The text can be **bold**!\n\n" +
      "1. You can have\n2. an ordered list like this!\n\n- Or it can be\n- an unordered list instead!\n\n\n" +
      "Finally, don't forget about images!\n![Tux the Linux Penguin](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXiRA6gjVegGI_RxD20jPt8mf2TVFcf-nU7w&s)";

const modifyCode = (changedCode) => {
  return {
    type: CODE_CHANGED,
    changedCode
  };
}


const codeReducer = (previousState, action) => {
  switch(action.type) {
    case CODE_CHANGED:
      return action.changedCode;

    default:
      return previousState;
  }
};

const store = createStore(codeReducer);

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

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <h1 className="text-center">React Markdown Editor</h1>
        <Editor />
      </div>
    );
  }
}

class Editor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      code: defaultCode
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState(() => ({
      code: event.target.value
    }));
  };

  render() {
    return (
      <div>
        <h3 className='text-center'>Editor</h3>
        <textarea id="editor" style={{width: "100%", height: "10em"}} onChange={this.handleChange} value={this.state.code}></textarea>
        <Display code={this.state.code}/>
      </div>
    );
  }
}

class Display extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    marked.use({
      gfm: true,
      breaks: true
    });

    return (
      <div>
        <h3 className='text-center'>Preview</h3>
        <div id="preview" dangerouslySetInnerHTML={{__html: marked.parse(this.props.code)}}></div>
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    code: state
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    newCode: (changedCode) => {
      dispatch(modifyCode(changedCode))
    }
  }
};

const Container = connect(mapStateToProps, mapDispatchToProps)(App)



Here are some pictures as to what the page looks like (It has the editor, and then renders the markdown in the preview):




This is what it looks like when I run the tests:

Any help is very appreciated. I know it is quite a bit to look over, so please bear with me. Please click the link below if you want to see all of the code in my project, and let me know if anything else is needed. Thank you very much for your time, and sorry for the inconvenience!

My GitHub Link

You are using several deprecated declarations. createStore is one of them, but still seems to work (see image).

Then there is the way you render the root in React and where you import ReactDOM from:

ReactDOM.render(<AppWrapper />, document.getElementById('page'));

This is how it should be done now:

import React from 'react';
import ReactDOM from "react-dom/client";
import './App.scss';
import AppWrapper from './App.jsx';

ReactDOM.createRoot(document.getElementById('page')).render(<AppWrapper />);

I recommend that you install the Redux extension from Chrome devtools. That will show you if you have Redux response in the first place and if the states reflect what you expect:

2 Likes

Hey thanks for the help! Sorry got busy and had to be away for a little bit. The reason I am using those old forms of React is because the tests are not updated to the newest version, but according to them, it shouldn’t make too much of a difference. As for the Redux extension, with it I can definitely say something is wrong because it is not showing any tree.

UPDATE: I got it to work! Turns out I needed to switch the redux to connect the editor component instead, and then I needed to remove the local state and use the dispatch property (newCode) when handling any change to the editor for it to work! Thank you so much for the help!

For anyone using this as reference in the future, here is the new code (all the changes should be marked with a comment denoting that it got changed):

import React from 'react';
import {Provider, connect} from 'react-redux';
import {createStore} from 'redux';
import {marked} from "https://cdnjs.cloudflare.com/ajax/libs/marked/13.0.2/lib/marked.esm.js";

const CODE_CHANGED = 'CODE CHANGED';
const defaultCode = "# This is the first header!\n" + 
      "## This is the second header!\n" +
      "You can create links with markdown such as this one to YouTube [Click Me!](https://www.youtube.com)\n" +
      "This is how a line of code is made: `console.log(\'hello world\')`.\n" +
      "The following is an inline code block:\n" +
      "```\nfunction showcase() {\n" +
      "    console.log(\'This is a function!\');\n" +
      "}\n```\n\n\n" +
      "You can create blockquotes like this: \n> Here is a blockquote\n\n" +
      "The text can be **bold**!\n\n" +
      "1. You can have\n2. an ordered list like this!\n\n- Or it can be\n- an unordered list instead!\n\n\n" +
      "Finally, don't forget about images!\n![Tux the Linux Penguin](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXiRA6gjVegGI_RxD20jPt8mf2TVFcf-nU7w&s)";

const modifyCode = (changedCode) => {
  return {
    type: CODE_CHANGED,
    changedCode
  };
}

// CHANGE MADE HERE (set the default state in the reducer instead, as it manages the changes being made)
const codeReducer = (previousState = defaultCode, action) => {
  switch(action.type) {
    case CODE_CHANGED:
      return action.changedCode;

    default:
      return previousState;
  }
};

// CHANGE MADE HERE (this is just for the redux devtools)
const store = createStore(codeReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

export default class AppWrapper extends React.Component {
  render() {
    return (
      <App />
    )
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    // CHANGE MADE HERE
    return (
      <div>
        <h1 className="text-center">React Markdown Editor</h1>
        <Provider store={store}>
          <Container />
        </Provider>
      </div>
    );
  }
}

class Editor extends React.Component {
  constructor(props) {
    super(props);
    // CHANGE MADE HERE
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    // CHANGE MADE HERE
    const updatedCode = event.target.value;
    this.props.newCode(updatedCode);
  };

  render() {
    return (
      <div>
        <h3 className='text-center'>Editor</h3>
        <textarea id="editor" style={{width: "100%", height: "10em"}} onChange={this.handleChange} value={this.props.code}></textarea>
        <Display code={this.props.code}/>
      </div>
    );
  }
}

class Display extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    marked.use({
      gfm: true,
      breaks: true
    });

    return (
      <div>
        <h3 className='text-center'>Preview</h3>
        <div id="preview" dangerouslySetInnerHTML={{__html: marked.parse(this.props.code)}}></div>
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  console.log('map state to props');
  return {
    code: state
  };
};

const mapDispatchToProps = (dispatch) => {
  console.log('map dispatch to props');
  return {
    newCode: (changedCode) => {
      dispatch(modifyCode(changedCode));
    }
  }
};

const Container = connect(mapStateToProps, mapDispatchToProps)(Editor);
1 Like