How can I create an instance of an Object in React..?

0

Issue

I am very new to react and javascript, but I am trying to build a simple ToDo App. It wasn’t complicated until I wanted to read data from a file and to display that data on the screen. The problem is that I don’t know how to create a new Todo object to pass it as parameter for addTodo function.. Thaaank you all and hope you can help me!!

I will let the code here (please see the -loadFromFile- function, there is the problematic place:

import React, { useState } from 'react';
import TodoForm from './TodoForm';
import Todo from './Todo';
import data from  './data/data.json'


function TodoList() {
  const [todos, setTodos] = useState([]);

  
  const loadFromFile = data.map( ( data) => {
    const newTodo = addTodo(new Todo(data.id,data.text));
    return  ( {newTodo} )});


  const addTodo = todo => {
    if (!todo.text || /^\s*$/.test(todo.text)) {
      return;
    }

    const newTodos = [todo, ...todos];

    setTodos(newTodos);
    console.log(...todos);
  };

  const updateTodo = (todoId, newValue) => {
    if (!newValue.text || /^\s*$/.test(newValue.text)) {
      return;
    }

    setTodos(prev => prev.map(item => (item.id === todoId ? newValue : item)));
  };

  const removeTodo = id => {
    const removedArr = [...todos].filter(todo => todo.id !== id);

    setTodos(removedArr);
  };

  const completeTodo = id => {
    let updatedTodos = todos.map(todo => {
      if (todo.id === id) {
        todo.isComplete = !todo.isComplete;
      }
      return todo;
    });
    setTodos(updatedTodos);
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      {loadFromFile}
      <Todo 
        todos={todos}
        completeTodo={completeTodo}
        removeTodo={removeTodo}
        updateTodo={updateTodo}
      />
    </>
  );
}

export default TodoList;

I want to create new instance of Todo object. I tried many times, many different forms, but still doesn’t work. I have an id and a text from the data.json file. I want to create that instance of Todo object with these two values. But how?

import React, { useState } from 'react';
import TodoForm from './TodoForm';
import EditIcon from '@material-ui/icons/Edit';
import DeleteIcon from '@material-ui/icons/Delete';


const Todo = ({ todos, completeTodo, removeTodo, updateTodo }) => {
  
  const [edit, setEdit] = useState({
    id: null,
    value: ''
  });

  const submitUpdate = value => {
    updateTodo(edit.id, value);
    setEdit({
      id: null,
      value: ''
    });
  };

  if (edit.id) {
    return <TodoForm edit={edit} onSubmit={submitUpdate} />;
  }

  return todos.map((todo, index) => (
    <div
      className={todo.isComplete ? 'todo-row complete' : 'todo-row'}
      key={index}
    >
      <p> <div key={todo.id} onClick={() => completeTodo(todo.id)}>
        {todo.text}
      </div> 
      </p>

      <div className='icons'>
        <DeleteIcon fontSize="small"
          onClick={() => removeTodo(todo.id)}
          className='delete-icon'
        />
        <EditIcon
          onClick={() => setEdit({ id: todo.id, value: todo.text })}
          className='edit-icon'
        />
      </div>
    </div>
  ));
};

export default Todo;

import React, { useState, useEffect, useRef } from 'react';
import { Fab, IconButton } from "@material-ui/core";
import AddIcon from '@material-ui/icons/Add';

function TodoForm(props) {
  const [input, setInput] = useState(props.edit ? props.edit.value : '');

  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  });

  const handleChange = e => {
    setInput(e.target.value);
  };

  const handleSubmit = e => {
    e.preventDefault();

    props.onSubmit({
      id: Math.floor(Math.random() * 10000),
      text: input
    });
    setInput('');
  };

  return (
    <form onSubmit={handleSubmit} className='todo-form'>
      {props.edit ? (
        <>
          <textarea cols="10"
            placeholder='Update item'
            value={input}
            onChange={handleChange}
            name='text'
            ref={inputRef}
            className='todo-input edit'
          />
          <button onClick={handleSubmit} className='todo-button edit'>
            Save
          </button>
        </>
      ) : (
        <>
          <input
            placeholder='Add item'
            value={input}
            onChange={handleChange}
            name='text'
            className='todo-input'
            ref={inputRef}
          />
          
          <Fab color="primary" aria-label="add"> 
            < AddIcon onClick={handleSubmit} fontSize="small" /> 
          </Fab>
        </>
      )}
    </form>
  );
}

export default TodoForm;

Solution

Issue

Ah, I see what you are getting at now, you are wanting to load some list of todos from an external file. The main issue I see in your code is that you are attempting to call/construct a Todo React component manually and this simply isn’t how React works. You render data/state/props into JSX and pass this to React and React handles instantiating the components and computing the rendered DOM.

const loadFromFile = data.map((data) => {
  const newTodo = addTodo(new Todo(data.id, data.text));
  return ({newTodo});
});

Todo shouldn’t be invoked directly, React handles this.

Solution

Since it appears the data is already an array of objects with the id and text properties, it conveniently matches what you store in state. You can simply pass data as the initial todos state value.

const [todos, setTodos] = useState(data);

If the data wasn’t readily consumable you could create an initialization function to take the data and transform/map it to the object shape your code needs.

const initializeState = () => data.map(item => ({
  id: item.itemId,
  text: item.dataPayload,
}));

const [todos, setTodos]= useState(initializeState);

Running Example:

import data from "./data.json";

function TodoList() {
  const [todos, setTodos] = useState(data); // <-- initial state

  const addTodo = (text) => {
    if (!text || /^\s*$/.test(text)) {
      return;
    }

    setTodos((todos) => [todo, ...todos]);
  };

  const updateTodo = (id, newTodo) => {
    if (!newTodo.text || /^\s*$/.test(newTodo.text)) {
      return;
    }

    setTodos((todos) => todos.map((todo) => (todo.id === id ? newTodo : todo)));
  };

  const removeTodo = (id) => {
    setTodos((todos) => todos.filter((todo) => todo.id !== id));
  };

  const completeTodo = (id) => {
    setTodos((todos) =>
      todos.map((todo) =>
        todo.id === id
          ? {
              ...todo,
              isComplete: !todo.isComplete
            }
          : todo
      )
    );
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      <Todo
        todos={todos}
        completeTodo={completeTodo}
        removeTodo={removeTodo}
        updateTodo={updateTodo}
      />
    </>
  );
}

Edit how-can-i-create-an-instance-of-an-object-in-react

Answered By – Drew Reese

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave A Reply

Your email address will not be published.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More