What could be causing my React child component to not update when changes are made to an array passed down in props after fetching new data?

My Profile.js component is responsible for fetching activity data related to a specific user from the URL parameter and updating the profileActivity state. This state is then passed down to my child component, ProfileActivity.js, where it should be displayed.

However, I'm facing an issue where the newly fetched data in ProfileActivity.js does not render immediately and only shows up after interacting with the page, such as clicking a button.

I've attempted to use the spread operator when setting the profileActivity state to ensure immutability, but this doesn't seem to resolve the problem. It's possible that I may have missed something in implementing this approach correctly. Additionally, I tried using the key={} attribute on the component without success.

What steps should I take to trigger an update in ProfileActivity.js as soon as setProfileActivity(activity) is called with the new data?

Within Profile.js:

function Profile(props) {
  const {parameter1} = props.match.params;
  const [profileViewing, setProfileViewing] = useState(null);
  const [profileDetails, setProfileDetails] = useState(null);
  const [profileActivity, setProfileActivity] = useState(null);
  const [loading, setLoading] = useState(true);

  // When URL parameters change, determine which profile to show
  useEffect(() => {
    if(parameter1) {
      setProfileViewing(parameter1);
    }
  }, [props, parameter1]);

  // When the profile being viewed (profileViewing state) changes, fetch and store the viewed profile's details and activity
  useEffect(() => {
    async function fetchProfileDetailsAndActivity(username) {
      try {
        const profile = await getUserDetailsFromUsername(username);
        setProfileDetails(profile);
        const activity = await 
        getActivityArray(profile.latestActivity);
        setProfileActivity(activity);
      } catch(error) {
        // Handle error
      }  
    }

    if(profileViewing) {
      fetchProfileDetailsAndActivity(profileViewing);
    }
  }, [profileViewing])

  // If profileDetails and profileActivity are no longer null, set loading to false
  useEffect(() => {
    if(profileDetails && profileActivity) {
      setLoading(false);
    }
  }, [profileDetails, profileActivity])

    return(
      <div className="Profile">
        <main>
          <div className="wrap">
            <div className="dual-right">
              <ProfileActivity profileDetails={profileDetails} profileActivity={profileActivity} loading={loading}/>
            </div>    
          </div>
        </main>
      </div>
    )
}

export default Profile;

In ProfileActivity.js:

const ProfileActivity = (props) => {
  const getActivityList = () => {
    let listItems = [];

    for(let i = 0; i < props.profileActivity.length; i++) {
      console.log(props.profileActivity[i])
      listItems.push(
        <p key={props.profileActivity[i].id}>Item {props.profileActivity[i].id}</p>
      )
    }

    return listItems;
  }

  if(props.loading) {
    return(
      <div className="box">
        <h3>Latest Activity</h3>   
        <div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div> 
      </div>
    )
  } else {
    return(
      <div className="box">
        <h3>Latest Activity</h3>   
          <ul>
            {getActivityList()} 
          </ul>
      </div>
    )
  }
}

export default ProfileActivity;

An example of the data returned from getUserDetailsFromUsername('somename'):

{ createdOn: it {
    seconds: 1635703629, 
    nanoseconds: 60000000
  },
  email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="285b47454d4649454d68494c4c5a4d5b5b064b4745">[email protected]</a>",
  latestActivity: [
    0: "FEnZZBcQph0oPtoOQErQ"
    1: "PuRQVS1OuRQNv42wCrlk" ],
  username: "somename" }

I pass the latestActivity array to getActivityArray(array), which takes the array of reference IDs, searches another database with them, compiles richer details into a new array, and returns it. Here is an example of the returned array with 1 activity:

[{ date: 1636129735609, 
   refs: { artist: "Rihanna"
           songID: "Gt8xVxzc9badIuEy0td1"
           title: "Umbrella" }, 
   type: 'addSong', 
   uid: 'ZvDymG7poeNw8MmIaA2hIONInA83', 
   id: 'FEnZZBcQph0oPtoOQErQ' }]

Answer №1

After some investigation, I was able to resolve the issue. It turns out that the problem originated from the getActivityArray() function rather than being related to React.

I realized that my approach to searching the database was inefficient. I was manually iterating over each ID in the array passed as a parameter and fetching relevant details using a getDoc() query for each item.

Upon making changes, I switched to using a Firebase getDocs() query, which allows me to search the collection for activity items based on the user's uid.

Looking back, it seems like such a straightforward solution that I should have implemented initially. Nevertheless, this experience served as a valuable lesson and highlighted the importance of efficient problem-solving techniques!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to configure node and express for file serving

Currently using Windows 7, I have successfully installed nodes 0.10.12 and the latest versions of express and express-generator globally. I then proceeded to create a new express project called nodetest1 and installed all dependencies using npm install. U ...

Navigating to a precise location on a webpage with React.js

I want to implement a straightforward action where the page automatically scrolls to a specific position upon loading. However, my attempts to execute this action have been unsuccessful so far. Is there an alternative method to achieve this in a React ap ...

What is the best way to distribute components between two NextJS projects?

Confused about the best way to share ReactJs components between two NextJs applications - one for e-commerce and the other for a manager portal. In the e-commerce app, there are various UI components that I want to reuse in the manager portal. Considering ...

Is there a way to deliberately trigger an error using Selenium WebDriverIO?

Is there a way to trigger an error using ChromeDriver with Selenium WebDriverIO? I'm not sure if there's a method like browser.fire('error'). ...

AngularJS - Controller not recognizing state name parameter

I'm a newcomer to angular and struggling to understand why this specific issue is occurring. Interestingly, when I use {{$state.current.name}} in my view, everything works as expected. However, the problem arises when I attempt to pass it to my contr ...

What is the best way to generate a new DIV every time a button is clicked?

I am attempting to make a square DIV that is red and measures 100x100 pixels. Each time a button is clicked, I want the square to be created. However, the code I have written is not functioning properly: <html> <title> Create New Div ...

Emphasize specific letters in a word by making them bold, according to the user

In my app, there is a search feature that filters data based on user input and displays a list of matching results. I am trying to make the text that was searched by the user appear bold in the filtered data. For example, if the user searches 'Jo&apos ...

Get connected to your favorite music on iTunes without the hassle of opening a new window by simply clicking on the

Is there a way to call a link to iTunes (itms://...) without opening a new window? I've tried using window.open but that just opens a new window. Also, $.get('itms://...'); doesn't seem to work for me. Are there any other options avail ...

Steps for selectively extracting objects from an array containing nested objectsNeed a way to isolate specific objects

Currently, I am working on a project in JavaScript and have created an array called folders that holds multiple objects: folders = [folder1, folder2, folder3...] Each object within the array has various properties, one of which is docs that is an array o ...

Load the flexslider once the fancybox container is opened

In my experience, I have found flexslider and fancybox to be very useful plugins. Individually, they work perfectly fine on a website that I am currently working on. However, when I tried placing a flexslider gallery inside a fancybox div, I encountered a ...

When you duplicate the React State object and make changes to the copied object, it directly affects

When attempting to duplicate a state object, I noticed that the state object is being modified directly in the code snippet below: @boundMethod private _onClickDeleteAttachment(attachmentName: string): void { console.log("_onClickDeleteAttachment | th ...

Leveraging batchWriteItem with dynamodb

I am trying to utilize batchWriteItem in my DynamoDB to add data to two tables: candidate table and user table. The formatted query is shown below: var user = { userid: usrid, role: 'candidate', password: vucrypt.encryptp ...

My goal is to implement a confirmation modal prior to any route changes within Next.js framework

Below is the code block that I have: const onRouteChangeStart = React.useCallback(() => { if (formState.isDirty) { if (window.confirm('Confirmation message')) { return true; } NProgress.done(); throw "A ...

How to easily transfer a JSON file to a server using Vue and Node.js

As a newcomer to the world of Node.js and Vue development, my goal is to establish a seamless process for users to create and upload a JSON file to the server when they save data in a form. This process should occur effortlessly in the background, allowing ...

Can a page name and folder name containing dynamic pages be identical?

insert image overview here In the image above, I have a section called "Movies" along with a directory named movies I am trying to navigate so that if the URL in the address bar is '/movies', it directs me to the "movies.js" page. Only when the ...

Converting dynamic content within a div into an interactive link

I am currently working with Longtail's JW Player and facing some difficulties with a basic function. Since I am not familiar with the programming language terminologies, I will describe the issue step by step: There is a JavaScript code that displays ...

Tips for verifying if the input in a Material UI textfield is an <iframe> tag

In my ReactJS code, I am utilizing the TextField component from material-ui. I need to verify if the user input is an iframe. How can I achieve this? Currently, I am attempting to use window.parent.frames.length > 0; to determine if the page contains a ...

Leverage the power of Google Maps within your Next JS application

Has anyone encountered the error Unhandled Runtime Error Invariant Violation: useGoogleMap needs a GoogleMap available up in the tree when trying to use useGoogleMap() within a NEXT JS component? I am looking for a way to access the Google Map inside my ...

Unveiling the Theme: Navigating the Material UI withStyles and WithTheme for Theme

const StyledSlider = withStyles({ root: { color: theme => theme.palette.primary.main } }, { withTheme: true })(Slider); Initially, I thought the withTheme option would allow access to the theme inside the withStyles function. However, since the t ...

A guide on how to alternate between ng-hide and ng-show using separate controllers by utilizing a shared factory toggle state instance

Using Angular 1.x, I have implemented two controllers where I want to display controller_2 if controller_1 is hidden. To achieve this, I am utilizing a factory method. Here is the snippet of my HTML code:- <div ng-controller="controller_1 as c1" ng- ...