Below is my initial default state values,
export const parameterInitialState = {
id: '',
name: '',
parameterSettings: parameterSettingsInitialState,
parameterMediaSettings: parameterMediaSettingsInitialState,
};
export const parameterSettingsInitialState = {
attributeId: '',
value: '',
};
export const parameterMediaSettingsInitialState = {
barcodeSupported: false,
mediaTypeId: '',
qrcodeSupported: false,
scratchOffPINSupported: false,
};
in the parameterState reducer, I use the above parameterInitialState
const initialState = {
parameterSettings: parameterInitialState,
};
export default function parameterState( state = initialState, action ) {
switch ( action.type ) {
case FETCH_PARAMETER_SUCCESS:{
return { ...state, ...action.payload };
}
default:
return state;
}
}
But my issue is in the initial state the object parameterSettings and parameterMediaSettings becomes undefined
Change the order in which your initial state variables are defined, in the given order variables parameterSettingsInitialState and parameterMediaSettingsInitialState will return undefined.
So make sure the child object variables are defined first followed by the parent object you plan include them in.
export const parameterSettingsInitialState = {
attributeId: '',
value: '',
};
export const parameterMediaSettingsInitialState = {
barcodeSupported: false,
mediaTypeId: '',
qrcodeSupported: false,
scratchOffPINSupported: false,
};
export const parameterInitialState = {
id: '',
name: '',
parameterSettings: parameterSettingsInitialState,
parameterMediaSettings: parameterMediaSettingsInitialState,
};
Updated answer withparameterSettingsInitialState and parameterMediaSettingsInitialState as arrays :
export const parameterSettingsInitialState = [{
attributeId: '',
value: '',
}];
export const parameterMediaSettingsInitialState = [{
barcodeSupported: false,
mediaTypeId: '',
qrcodeSupported: false,
scratchOffPINSupported: false,
}];
export const parameterInitialState = {
id: '',
name: '',
parameterSettings: parameterSettingsInitialState,
parameterMediaSettings: parameterMediaSettingsInitialState,
};
Related
When the value of an reactive object is changed, a prop in my Pinia store is mutated. I tried different ways of attributing new value to this store to avoid this problem, but so far I dont't really understand what is happenning. This is my code:
Component
const form = reactive({
name: "",
exercises: [{ exercise: "", method: "", series: "" }],
});
const handleChange = ({ value, name }: any, eventIndex: any) => {
const newEx = form.exercises.map((ex, index) => ({
...ex,
...(index === eventIndex ? { [name]: value } : null),
}));
const newForm = { name: form.name, exercises: newEx };
Object.assign(form, newForm)
};
const onSubmit = async () => {
const { valid } = await formRef.value.validate();
if (!valid) return;
const storeTraining = workoutStore.newWorkout.training || [];
const workout = {
...workoutStore.newWorkout,
training: [...storeTraining, form],
};
workoutStore.setNewWorkout(workout);
isOpen.value = false;
};
Store
import { ref, computed } from "vue";
import { defineStore } from "pinia";
import type { IUser } from "#/domain/users/type";
import type { ITraining, IWorkout } from "#/domain/workouts/types";
export const useWorkoutStore = defineStore("workouts", () => {
const creatingWorkoutStudent = ref<IUser | null>(null);
const newWorkout = ref<Partial<IWorkout>>({});
const setCreatingWorkoutStudent = (newUser: IUser) => {
creatingWorkoutStudent.value = newUser;
};
const setNewWorkout = (workout: Partial<IWorkout>) => {
newWorkout.value = { ...workout };
return newWorkout.value;
};
const addNewTraining = (training: ITraining) => {
newWorkout.value.training
? newWorkout.value.training.push(training)
: (newWorkout.value.training = [training]);
};
const reset = () => {
newWorkout.value = {};
creatingWorkoutStudent.value = null;
};
return {
creatingWorkoutStudent,
setCreatingWorkoutStudent,
newWorkout,
setNewWorkout,
reset,
addNewTraining,
};
});
And this is a example of an input that mutates reactive values
<text-field
label="ExercĂcio"
#input="
handleChange(
{ value: $event.target.value, name: 'exercise' },
index
)
"
:value="exercise.exercise"
:rules="[validationRules.required]"
/>
Every time that a input changes a value in const form = reactive(), the same property in Pinia store is changed too.
I've created a fiddle to exemplify my issue here
I am trying to implement #toast-ui/react-calendar, initially I was getting window is not defined but after implementing the fix I got here https://github.com/nhn/toast-ui.react-calendar/issues/39, I got this instead Unhandled Runtime Error Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of __WEBPACK_DEFAULT_EXPORT__.
This is my curent code
CalendarPage.js
import React from 'react';
import Calendar from '#toast-ui/react-calendar';
import 'tui-calendar/dist/tui-calendar.css';
import 'tui-date-picker/dist/tui-date-picker.css';
import 'tui-time-picker/dist/tui-time-picker.css';
export default (props) => <Calendar {...props} ref={props.forwardedRef} />;
schedule>index.jsx
import { forwardRef, useCallback, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
const TuiCalendar = dynamic(() => import('#components/calendars/CalendarPage'), { ssr: false });
const CalendarWithForwardedRef = forwardRef((props, ref) => (
<TuiCalendar {...props} forwardedRef={ref} />
));
const start = new Date();
const end = new Date(new Date().setMinutes(start.getMinutes() + 30));
const schedules = [
{
calendarId: '1',
category: 'time',
isVisible: true,
title: 'Study',
id: '1',
body: 'Test',
start,
end,
},
{
calendarId: '2',
category: 'time',
isVisible: true,
title: 'Meeting',
id: '2',
body: 'Description',
start: new Date(new Date().setHours(start.getHours() + 1)),
end: new Date(new Date().setHours(start.getHours() + 2)),
},
];
const calendars = [
{
id: '1',
name: 'My Calendar',
color: '#ffffff',
bgColor: '#9e5fff',
dragBgColor: '#9e5fff',
borderColor: '#9e5fff',
},
{
id: '2',
name: 'Company',
color: '#ffffff',
bgColor: '#00a9ff',
dragBgColor: '#00a9ff',
borderColor: '#00a9ff',
},
];
const SchedulePage = () => {
const cal = useRef(null);
const onClickSchedule = useCallback((e) => {
const { calendarId, id } = e.schedule;
const el = cal.current.calendarInst.getElement(id, calendarId);
console.log(e, el.getBoundingClientRect());
}, []);
const onBeforeCreateSchedule = useCallback((scheduleData) => {
console.log(scheduleData);
const schedule = {
id: String(Math.random()),
title: scheduleData.title,
isAllDay: scheduleData.isAllDay,
start: scheduleData.start,
end: scheduleData.end,
category: scheduleData.isAllDay ? 'allday' : 'time',
dueDateClass: '',
location: scheduleData.location,
raw: {
class: scheduleData.raw['class'],
},
state: scheduleData.state,
};
cal.current.calendarInst.createSchedules([schedule]);
}, []);
const onBeforeDeleteSchedule = useCallback((res) => {
console.log(res);
const { id, calendarId } = res.schedule;
cal.current.calendarInst.deleteSchedule(id, calendarId);
}, []);
const onBeforeUpdateSchedule = useCallback((e) => {
console.log(e);
const { schedule, changes } = e;
cal.current.calendarInst.updateSchedule(schedule.id, schedule.calendarId, changes);
}, []);
function _getFormattedTime(time) {
const date = new Date(time);
const h = date.getHours();
const m = date.getMinutes();
return `${h}:${m}`;
}
function _getTimeTemplate(schedule, isAllDay) {
var html = [];
if (!isAllDay) {
html.push('<strong>' + _getFormattedTime(schedule.start) + '</strong> ');
}
if (schedule.isPrivate) {
html.push('<span class="calendar-font-icon ic-lock-b"></span>');
html.push(' Private');
} else {
if (schedule.isReadOnly) {
html.push('<span class="calendar-font-icon ic-readonly-b"></span>');
} else if (schedule.recurrenceRule) {
html.push('<span class="calendar-font-icon ic-repeat-b"></span>');
} else if (schedule.attendees.length) {
html.push('<span class="calendar-font-icon ic-user-b"></span>');
} else if (schedule.location) {
html.push('<span class="calendar-font-icon ic-location-b"></span>');
}
html.push(' ' + schedule.title);
}
return html.join('');
}
const templates = {
time: function (schedule) {
console.log(schedule);
return _getTimeTemplate(schedule, false);
},
};
return (
<div className='App'>
<h1>Welcome to TOAST Ui Calendar</h1>
<CalendarWithForwardedRef
ref={cal}
height='1000px'
useCreationPopup={true}
useDetailPopup={true}
calendars={calendars}
schedules={schedules}
onClickSchedule={onClickSchedule}
onBeforeCreateSchedule={onBeforeCreateSchedule}
onBeforeDeleteSchedule={onBeforeDeleteSchedule}
onBeforeUpdateSchedule={onBeforeUpdateSchedule}></CalendarWithForwardedRef>
</div>
);
};
export default SchedulePage;
I do not what I am doing wrong here but I keep getting this error
Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `__WEBPACK_DEFAULT_EXPORT__`.
Call Stack
createFiberFromTypeAndProps
node_modules\react-dom\cjs\react-dom.development.js (25058:0)
createFiberFromElement
node_modules\react-dom\cjs\react-dom.development.js (25086:0)
reconcileSingleElement
node_modules\react-dom\cjs\react-dom.development.js (14052:0)
reconcileChildFibers
node_modules\react-dom\cjs\react-dom.development.js (14112:0)
Turns out that the issue with my code was caused by clashing npm packages, I had react-big-calendar installed previously removing that fixed the issue
I have super simple question
Why my redux state doesn't update immediately?
const { reducer, actions } = createSlice({
name: "professionals",
initialState: {
loading: false,
lastFetchList: undefined,
list: undefined,
professional: undefined,
filters: {
virtual: false
}
},
reducers: {
professionalsListRequested: (professionals, action) => {
if (action.payload.withLoading) professionals.loading = true;
},
professionalsListRequestFailed: (professionals, action) => {
professionals.loading = false;
},
professionalsListReceived: (professionals, action) => {
professionals.lastFetchList = Date.now();
professionals.list = action.payload.data.dataArr;
professionals.loading = false;
},
virtualUpdated: (categories, action) => {
categories.filters.virtual = action.payload;
}
},
});
export const { virtualUpdated } = actions;
export default reducer;
it is my slice.
and here is code of the component :
const dispatch = useDispatch();
const filters = useSelector((state) => state.professionals.filters);
const handlePressOnVirtual = async () => {
console.log("Before" , filters.virtual)
await dispatch(virtualUpdated(!filters.virtual));
console.log("after" , filters.virtual)
};
when handlePressOnVirtual function is called the both console.log(s) print previous value of the state.
When you are still in handlePressOnVirtual function, you are still in a closure, so all the references will still be your existing filters
So you would need to wait for another re-render for useSelector to invoke again then the new values will come.
One way to see the latest changes is to put your log inside a useEffect:
useEffect(() => {
console.log("after" , filters.virtual)
},[filters.virtual]);
Here my redux state , the state has dynamic nested object name
const search = {
client :
{ result: [],
selected: null,
isLoading: false,
isSuccess: false,},
[dynamicKey] :
{ result: [],
selected: null,
isLoading: false,
isSuccess: false,},
[dynamicKey2] :
{ result: [],
selected: null,
isLoading: false,
isSuccess: false,}
};
I'm trying to get nested object by dynamic key , here is my selector code :
import { createSelector } from "reselect";
export const searchState = (state) => state.search;
export const selectSearch = (keyRef) =>
createSelector([searchState], (search) => search[keyRef]);
You forgot to ask the question but your code looks fine as it is. In the component you can use useMemo to not needlessly create the selector:
//renamed the selector to create...
export const createSelectSearch = (keyRef) =>
createSelector([searchState], (search) => search[keyRef]);
//compnent example
const MyComponent = ({keyRef}) => {
const selectSearch = React.useMemo(
()=>createSelector(keyRef),//create the selector when keyRef changes
[keyRef]
);
const result = useSelector(selectSearch)
return <jsx />
}
Some more information about this pattern can be found here
I was trying to reset the data, and want to go to initial state ,I know that the immutability playing major role in this part.
Below is my store data (Flow Completed data)
animalSense: {
selectedVision: 'dayLight',
selectedState: 'california',
viewedVisions: ['dayLightcalifornia', 'dayLightsouthAfrica', 'nightVisioncalifornia'],
viewedAnimals: ['dog', 'cat']
},
I want to replace it with the below data
animalSense: {
selectedVision: '',
selectedState: '',
viewedVisions: [''],
viewedAnimals: []
},
I know the below action is the Straight and proper way to add initial data is
export const RESET_ANIMAL_SENSES = 'actions/reset_animal_senses';
export default () => ({
type: RESET_ANIMAL_SENSES,
payload: {
selectedVision: '',
selectedState: '',
selectedAnimal: '',
viewedVisions: [''],
viewedAnimals: []
}
});
But the above action maintaining the same state
Below action is Working Solution but I don't know is this a Proper way
export const RESET_ANIMAL_SENSES = 'actions/reset_animal_senses';
const data = JSON.stringify({
selectedVision: '',
selectedState: '',
selectedAnimal: '',
viewedVisions: [''],
viewedAnimals: []
});
export default () => ({
type: RESET_ANIMAL_SENSES,
payload: JSON.parse(data)
});
When we are using stringify the connectivity has been ended and the new state has been added but i don't know why this is not working without JSON.stringify()?
Reducer
import { SELECT_VISION } from '../actions/select_vision_type';
import { CHANGE_ANIMAL_VIDEO_STATE } from '../actions/change_animal_video_state';
import { UPDATE_ANIMALS } from '../actions/update_animals';
import { RESET_ANIMAL_SENSES } from '../actions/reset_animal_senses';
export default (state = {}, action) => {
let newState = state;
switch (action.type) {
case SELECT_VISION:
newState = { ...state, ...action.payload };
break;
case CHANGE_ANIMAL_VIDEO_STATE:
newState = { ...state, ...action.payload };
break;
case UPDATE_ANIMALS:
newState = { ...state, ...action.payload };
break;
case RESET_ANIMAL_SENSES:
newState = { ...state, ...action.payload };
break;
default:
break;
}
return newState;
};
Spread Operator in payload Solved this issue
export const RESET_ANIMAL_SENSES = 'actions/reset_animal_senses';
const data = {
selectedVision: '',
selectedState: '',
selectedAnimal: '',
viewedVisions: [''],
viewedAnimals: []
};
export default () => ({
type: RESET_ANIMAL_SENSES,
payload: { ...data } // here is the solution
});
Try this out, I'd do good amount of refactors to your reducer.
import { SELECT_VISION } from '../actions/select_vision_type';
import { CHANGE_ANIMAL_VIDEO_STATE } from '../actions/change_animal_video_state';
import { UPDATE_ANIMALS } from '../actions/update_animals';
import { RESET_ANIMAL_SENSES } from '../actions/reset_animal_senses';
const initialState = {
selectedVision: '',
selectedState: '',
selectedAnimal: '',
viewedVisions: [''],
viewedAnimals: []
}
export default (state = initialState, action) => {
switch (action.type) {
// since all the cases have common code.
case SELECT_VISION:
case CHANGE_ANIMAL_VIDEO_STATE:
case UPDATE_ANIMALS: {
return { ...state, ...action.payload }
}
case RESET_ANIMAL_SENSES: {
return { ...initialState }
}
default: {
return state;
}
}
};
Try this reducer once. However, currently I don't have a clarity on why would it work with stringify in place.