skip to Main Content

I have an external module file Task.ts which has the following:

const taskList: Task[] = [];

Class Task {
    ...
}

export { Task, taskList }

And taskList is a list of Task objects that is modified by the Task class.

Then I have my main app.tsx file. And I’m importing the list and the class like so:

import { Task, taskList } from "./Task"

So I’m just wondering if there is a way to link taskList to a react state so that changes to taskList through the Task object will trigger a re-render. I’ve tried useEffect and putting taskList in the dependency array, but that hasn’t worked.

2

Answers


  1. If taskList can be updated from outside the App component or its childrens then you have to handle an event somehow and trigger useEffect to run to get the updated taskList array then update the state that holds taskList.
    I can think of emit a socket event each time you update taskList and listen for it from useEffect in App this will make the component rerender with the updated data when taskList is updated.

    otherwise you can update your state each time you update taskList, make each method of Task not only do its work but also returning taskList so you can easely call it and update the state after each change.

    Login or Signup to reply.
  2. You can use useState and here is a simple example:

    The function updateList is responsible for modifying the tasks state variable when a new task is added. It takes the newTaskContent as a parameter, creates a new Task object with the provided content, and then updates the tasks state variable by adding the new task to the existing list (taskList) using the spread operator (…).
    the tasks will automatically re-render when the state variable tasks is updated using the setTasks function.

    import React, { useState } from 'react';
    import { Task, taskList } from './Task';
    
    const App = () => {
      const [tasks, setTasks] = useState(taskList);
      const [taskContent, setTaskContent] = useState('');
    
      // Function to modify the taskList and trigger re-render
      const updateList = (newTaskContent) => {
        const task = {
          isDone: false,
          content: newTaskContent,
        }
        const newTask = new Task(task);
        const updatedTaskList = [...tasks, newTask];
    
        // Update the state variable to trigger re-render
        setTasks(updatedTaskList);
        setTaskContent(''); // Clear input field after adding task
      };
    
      return (
        <div>
          {tasks.map((task, idx) => (
            <div key={idx + 1}>{task.content}</div>
          ))}
    
          <input
            type="text"
            value={taskContent}
            onChange={(e) => setTaskContent(e.target.value)}
          />
    
          <button onClick={() => updateList(taskContent)}>Add Task</button>
        </div>
      );
    };
    
    export default App;

    Here is a simplify using vanilla JavaScript, and in addition to the example below, useState takes care of re-rendering the objects when it changes.

    // Array of objects 
    var tasks = [
      {
         isDone: true, 
         content: "Learn JavaScript"
       }
    ];
    
    // The class Task
    class Task {
      constructor(content, isDone=false) {
        this.isDone = isDone;
        this.content = content;
      }
    }
    
    // Add a new task function
    const addTask = (newTaskContent) => {
      // Create a new Task object
      const newTask = new Task(newTaskContent);  
      // Update the array using spread operator
      tasks = [...tasks, newTask];
      console.log(tasks);
    };
    
    // Call addTask function and pass the content
    addTask("Learn C++");

    More about useState and re-rendering:

    ReactJS | How does React associate Hook calls with components?

    Medium | React Hooks – Understanding Component Re-renders

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search