Home > OS >  React converting class into function component issues
React converting class into function component issues

Time:09-16

I am trying to use React Scheduler with my shifts database. The current state after trying to use hooks instead of class is that I cannot edit any field in the form. I have deleted some of the code to make it cleaner, for now I am trying only to add a shift.

React Scheduler original code:

import * as React from 'react';
import Paper from '@material-ui/core/Paper';
import { ViewState, EditingState } from '@devexpress/dx-react-scheduler';
import {
  Scheduler,
  Appointments,
  AppointmentForm,
  AppointmentTooltip,
  WeekView,
} from '@devexpress/dx-react-scheduler-material-ui';
import { appointments } from '../../../demo-data/appointments';

export default class Demo extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      data: appointments,
      currentDate: '2018-06-27',
      addedAppointment: {},
      appointmentChanges: {},
      editingAppointment: undefined,
    };

    this.commitChanges = this.commitChanges.bind(this);
    this.changeAddedAppointment = this.changeAddedAppointment.bind(this);
    this.changeAppointmentChanges = this.changeAppointmentChanges.bind(this);
    this.changeEditingAppointment = this.changeEditingAppointment.bind(this);
  }

  changeAddedAppointment(addedAppointment) {
    this.setState({ addedAppointment });
  }

  changeAppointmentChanges(appointmentChanges) {
    this.setState({ appointmentChanges });
  }

  changeEditingAppointment(editingAppointment) {
    this.setState({ editingAppointment });
  }

  commitChanges({ added, changed, deleted }) {
    this.setState((state) => {
      let { data } = state;
      if (added) {
        const startingAddedId = data.length > 0 ? data[data.length - 1].id   1 : 0;
        data = [...data, { id: startingAddedId, ...added }];
      }
      return { data };
    });
  }

  render() {
    const {
      currentDate, data, addedAppointment, appointmentChanges, editingAppointment,
    } = this.state;

    return (
      <Paper>
        <Scheduler
          data={data}
          height={660}
        >
          <ViewState
            currentDate={currentDate}
          />
          <EditingState
            onCommitChanges={this.commitChanges}
            addedAppointment={addedAppointment}
            onAddedAppointmentChange={this.changeAddedAppointment}
            appointmentChanges={appointmentChanges}
            onAppointmentChangesChange={this.changeAppointmentChanges}
            editingAppointment={editingAppointment}
            onEditingAppointmentChange={this.changeEditingAppointment}
          />
          <WeekView
            startDayHour={9}
            endDayHour={17}
          />
          <Appointments />
          <AppointmentTooltip
            showOpenButton
            showDeleteButton
          />
          <AppointmentForm />
        </Scheduler>
      </Paper>
    );
  }
}

My function component code:

import React, { useState } from 'react';
import Paper from '@material-ui/core/Paper';
import { ViewState, EditingState } from '@devexpress/dx-react-scheduler';
import {
  Scheduler,
  Appointments,
  AppointmentForm,
  AppointmentTooltip,
  WeekView,
  ConfirmationDialog,
} from '@devexpress/dx-react-scheduler-material-ui';
  
const DataSheet = ( { addShift, shifts, deleteShift } ) => {
    const [data, setData] = useState(shifts)
    const [currentDate, setCurrentDate] = useState('2018-06-27')
    const [addedAppointment, setAddedAppointment] = useState({})
    const [appointmentChanges, setAppointmentChanges] = useState({})
    const [editingAppointment, setEditingAppointment] = useState(undefined)
  
    const changeAddedAppointment = (addedAppointment) => {
        setAddedAppointment({ addedAppointment });
    }

    const changeAppointmentChanges = (appointmentChanges) => {
        setAppointmentChanges({ appointmentChanges });
    }

    const changeEditingAppointment = (editingAppointment) => {
        setEditingAppointment({ editingAppointment });
    }

    const commitChanges = ({ added, changed, deleted }) => {
    setData ((????) => {
      let { data } = data;
      console.log(data);  //returns undefined
      if (added) {
        const startingAddedId = data > 0 ? data[data.length - 1].id   1 : 0;  
        data = [...data, { id: startingAddedId, ...added }];
        addShift(added);
      }
      return { data };
    });
  }

    return (
      <Paper>
        <Scheduler
          data={data}
          height={660}
        >
          <ViewState
            currentDate={currentDate}
          />
          <EditingState
            onCommitChanges={commitChanges}
            addedAppointment={addedAppointment}
            onAddedAppointmentChange={changeAddedAppointment}
            appointmentChanges={appointmentChanges}
            onAppointmentChangesChange={changeAppointmentChanges}
            editingAppointment={editingAppointment}
            onEditingAppointmentChange={changeEditingAppointment}
          />
          <WeekView
            startDayHour={9}
            endDayHour={17}
          />
          <Appointments />
          <AppointmentTooltip
            showOpenButton
            showDeleteButton
          />
          <AppointmentForm />
        </Scheduler>
      </Paper>
    );
}

export default DataSheet

App.js:

import React from 'react';
import backgroundImage from './Resources/BennyBackground.jpeg'
import Header from "./components/Header";
import { useState, useEffect } from "react"
import DataSheet from './components/DataSheet';

const containerStyle= {
  width: '100vw',
  height: '100vh',
  backgroundImage: `url(${backgroundImage})`,
  backgroundPosition: 'center',
  backgroundSize: 'cover',
  backgroundRepeat: 'no-repeat',
}

const App = () => {
  const [shifts, setShifts] = useState([])
  useEffect(() => {
    const getShifts = async () => {
      const shiftsFromServer = await fetchShifts()
      setShifts(shiftsFromServer)
    }
    getShifts()
  }, [])

  const fetchShifts = async () => {
    const res = await fetch(`http://localhost:5000/shifts/`)
    const data = await res.json()
    return data
  }

const addShift = async (shift) => {
  const startingAddedId = shifts.length > 0 ? shifts[shifts.length - 1].id   1 : 0;
  shift.id = startingAddedId;
  const res = await fetch(`http://localhost:5000/shifts/`,{
    method: 'POST',
    headers: {
      'Content-type': 'application/json'
    },
    body: JSON.stringify(shift)
  })

  const data = await res.json()

  setShifts([...shifts, data])
} 

  return (
    <div className="container"
    style={containerStyle} >
      <div className='secondary_container'>
        <Header />
        <DataSheet shifts={shifts} addShift={addShift}/>
      </div>
    </div>
  );
}

export default App;

I know it is a lot of code and a lot to ask and I would highly appreciate help with this.

CodePudding user response:

I believe the issue is that you are using setXxx as you would use this.setState. In class components, you have one function that modifies all the state (this.setState), while in function components you have a setter function for each field.

So change this:

const changeAddedAppointment = (addedAppointment) => {
    setAddedAppointment({ addedAppointment });
}

to this:

const changeAddedAppointment = (addedAppointment) => {
    setAddedAppointment(addedAppointment);
}

As far as the commitChanges function goes, you can do the data manipulation before using setData. Also I'm not sure that this let { data } = data would work since there is already a data field. You can try this:

const commitChanges = ({ added, changed, deleted }) => {
    let newData = [...data.data];
    if (added) {
        const startingAddedId = newData > 0 ? newData [data.length - 1].id   1 : 0;  
        newData = [...newData , { id: startingAddedId, ...added }];
        addShift(added);
      }
    setData(newData);
};
  • Related