0

Repo for reference: https://github.com/G-bot987/NextDnDCharacterManager

I should start by explaining I'm completely new to redux, so the code I've written may fly in the face of best practice, in which case I'd like to know!

been stuck on this issue for a day or so now, I final have the ability to save data to a redux store. I seem to having some issues with propagation or duplication which the code I've written fixes without addressing the route cause. The wrapping of the return in a if statement inside of the case in the LanguageSlice.ts (file below)

The point of the store is to hold global state for language properties this state wont exist at all until the state is added with the 'selected' boolean with a true value, so the creation of the language property will add the data in following format, with selected set to true:

export interface languageInterface {
  value: string;
  selected?: boolean;
}

however there after, when a user clicks on the language property which is presented with a button, I want to toggle the selected boolean from true to false, with any future clicks flipping the state of selected. so if it is true a click with turn it false and if it is false a click will set it to true.

code:

_app.tsx, store initialized

import "../styles/globals.css";
import type { AppProps } from "next/app";
import { store } from "../store";
import { Provider } from "react-redux";


export default function App({ Component, pageProps }: AppProps) {
  return (
    <Provider store={store}>
      <Component {...pageProps} />
    </Provider>
  );
}

store.ts

import { configureStore } from "@reduxjs/toolkit";

import { languagePropertiesReducer } from "./slices/languageSlice";

export const store = configureStore({
  reducer: {
    languagePropertiesReducer: languagePropertiesReducer,
  },
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

languageSlice.ts

There seems to be so much wrong with this file, but it is the most successful iteration of my progress.

Within the switch a user clicks on a language property to add it, their are four different language properties. The property is then added to the redux store this functionality works, as it has been clicked the selected attribute of the language property is also true, at this stage. Before it is clicked there is nothing in the redux store. There is definately something wrong with the adding func, as when one of the four language properties is selected it is successfully added, but with its selected boolean set to false (it should be true), but the three other possible language properties are added to the store with their selected boolean set to false as well.

import { RootState } from "../store";

export interface LanguageProficiencyState {
  languagesArray: languageInterface[];
}
export interface languageInterface {
  value: string;
  selected?: boolean;
}
const initialState: LanguageProficiencyState = {
  languagesArray: [],
};

// actions

export const addLanguagePro = (test: any) => ({
  type: "ADD_LANGUAGE_PROFICIENCY",
  payload: test,
});

const removeLanguagePro = () => {
  return {
    type: "REMOVE_LANGUAGE_PROFICIENCY",
  };
};

// reducers
export function languagePropertiesReducer(state = initialState, action: any) {
  switch (action.type) {
    case "ADD_LANGUAGE_PROFICIENCY":
      const { value, selected } = action.payload;
      const { languagesArray } = state;
      const languageProperty = languagesArray.find(
        (languageProperty) => languageProperty.value === value
      );
      if (languageProperty === undefined) {
        console.log("does not exists so adding");
        return {
          ...state,
          languagesArray: [...state.languagesArray, action.payload],
        };
      } else {

        return {
          languagesArray: [
            ...state.languagesArray.filter((x) => x !== action.payload),
          ],
        };
      }

    default:
      return state;
  }
}

export const rootState = (state: RootState) =>
  state.languagePropertiesReducer.languagesArray;

Languageproperty.tsx

you can see clicking on the language property wrapped in the p tag represents in effect a toggle btn, however getting a click on this to represent 'create, update' seems to be difficult I'm not sure if I'm approaching this is the write way and maybe create and delete is the way to go, however I'm not sure how this will interact with the useState functionality of changing background colour. The whole point of this is the Languageproperty.tsx is a deeply nested comp and I wish to have a list that displays all selected language properties highier up the tree, I will then grab these from a redux store and render, I was doing this through local storage. However for scalability and to get me away from the restrictions of key value pairs I want to intergrate redux.

import React, { useState, useEffect } from "react";

import styles from "../../../../../styles/Home.module.css";

// redux
import { useSelector, useDispatch } from "react-redux";
import { addLanguagePro, rootState } from "../../../../../slices/languageSlice";

interface PropsInterface {
  language: string;
  dialectLanguage?: string;
  written?: boolean | null;
  spoken?: boolean | null;
  inflection?: boolean | null;
  proficiency?: boolean | null;
}

export default function Languageproperty(Props: PropsInterface) {
  const count = useSelector(rootState);
  const dispatch = useDispatch();

  const { language, dialectLanguage } = Props;
  const keysForNoDialect = Object.keys(Props);
  const property = keysForNoDialect[0];

  const [selected, setSelect] = useState(() => {
    if (typeof window !== "undefined") {

// I was using local storage so this can be ignored I'm transferring the functionality to //redux, the local storage method was working but is not scalable
      if (typeof dialectLanguage === "string") {
        const saved: any = localStorage.getItem(
          language + property + dialectLanguage
        );

        const intialValue = JSON.parse(saved);
        return intialValue || false;
      } else {
        const saved: any = localStorage.getItem(language + property);

        const intialValue = JSON.parse(saved);
        return intialValue || false;
      }
    }
  });
  useEffect(() => {
    if (typeof dialectLanguage === "string") {
      // localStorage.setItem(
      //   language + property + dialectLanguage,
      //   JSON.stringify(selected)
      // );
      const value = language + property + dialectLanguage;
      const languageProperty = { value, selected: selected };

      dispatch(addLanguagePro(languageProperty));
    } else {
      // localStorage.setItem(language + property, JSON.stringify(selected));
      const value = language + property;
      const languageProperty = { value, selected: selected };

      dispatch(addLanguagePro(languageProperty));
    }
    // storing
  }, [selected, language, property, dialectLanguage, dispatch]);

  return (
    <p
      onClick={() => setSelect(!selected)}
      style={{
        background: selected ? "purple" : "",
      }}
    >
      {property}
    </p>
  );
}

did some research on thunks and side effects, not sure if it permitted and looked at modules such as redux loop

G-bot987
  • 1
  • 1

0 Answers0