7

This Codesandbox only has mobile styles as of now

I currently have a list of items being rendered based on their status.

Goal: When the user clicks on a nav button inside the modal, it updates the status type in context. Another component called SuggestionList consumes the context via useContext and renders out the items that are set to the new status.

Problem: The value in context is definitely being updated, but the SuggestionList component consuming the context is not re-rendering with a new list of items based on the status from context.

This seems to be a common problem:

Does new React Context API trigger re-renders?

React Context api - Consumer Does Not re-render after context changed

Component not re rendering when value from useContext is updated

I've tried a lot of suggestions from different posts, but I just cannot figure out why my SuggestionList component is not re-rendering upon value change in context. I'm hoping someone can give me some insight.

Context.js

// CONTEXT.JS

import { useState, createContext } from 'react';

export const RenderTypeContext = createContext();

export const RenderTypeProvider = ({ children }) => {
  const [type, setType] = useState('suggestion');

  const renderControls = {
    type,
    setType,
  };

  console.log(type); // logs out the new value, but does not cause a re-render in the SuggestionList component

  return (
    <RenderTypeContext.Provider value={renderControls}>
      {children}
    </RenderTypeContext.Provider>
  );
};

SuggestionPage.jsx

   // SuggestionPage.jsx
    
    export const SuggestionsPage = () => {
      return (
        <>
          <Header />
          <FeedbackBar />
          <RenderTypeProvider>
            <SuggestionList />
          </RenderTypeProvider>
        </>
      );
    };

SuggestionList.jsx

// SuggestionList.jsx

import { RenderTypeContext } from '../../../../components/MobileModal/context';

export const SuggestionList = () => {
  const retrievedRequests = useContext(RequestsContext);
  const renderType = useContext(RenderTypeContext);
  const { type } = renderType;

  const renderedRequests = retrievedRequests.filter((req) => req.status === type);

  return (
    <main className={styles.container}>
      {!renderedRequests.length && <EmptySuggestion />}
      {renderedRequests.length &&
        renderedRequests.map((request) => (
          <Suggestion request={request} key={request.title} />
        ))}
    </main>
  );
};

Button.jsx

// Button.jsx

import { RenderTypeContext } from './context';

export const Button = ({ handleClick, activeButton, index, title }) => {
  const tabRef = useRef();
  const renderType = useContext(RenderTypeContext);
  const { setType } = renderType;

  useEffect(() => {
    if (index === 0) {
      tabRef.current.focus();
    }
  }, [index]);

  return (
    <button
      className={`${styles.buttons} ${
        activeButton === index && styles.activeButton
      }`}
      onClick={() => {
        setType('planned');
        handleClick(index);
      }}
      ref={index === 0 ? tabRef : null}
      tabIndex="0"
    >
      {title}
    </button>
  );
};

Thanks

Nunchuk
  • 312
  • 3
  • 13

1 Answers1

10

After a good night's rest, I finally solved it. It's amazing what you can miss when you're tired.

I didn't realize that I was placing the same provider as a child of itself. Once I removed the child provider, which was nested within itself, and raised the "parent" provider up the tree a little bit, everything started working.

So the issue wasn't that the component consuming the context wasn't updating, it was that my placement of providers was conflicting with each other. I lost track of my component tree. Dumb mistake.

The moral of the story, being tired can make you not see solutions. Get rest.

Nunchuk
  • 312
  • 3
  • 13