CodeSandbox
Trying to useState inside setInterval of a preact/hook. This isn't working, looks like for ever iteration it's executing previous callstacks(?). Could someone help me understand and help me fix so this snippet works?
import {h} from 'preact';
import {useState} from 'preact/hooks'
const interests = [
{name: 'the future',},
{name: 'architecture',},
{name: 'my work',},
{name: 'your work',},
{name: 'collaboration',},
{name: 'dank memes',},
{name: 'OOP vs. Functional',},
{name: 'design',},
{name: 'guitar',},
{name: 'inspirational people',},
{name: 'love',},
{name: 'travel',},
{name: 'singularity',},
{name: 'creativity',},
{name: 'mixed, virtual, augmented reality',},
{name: 'art',},
{name: 'imagination',},
{name: 'problem solving',},
{name: 'space',},
{name: 'cooking',},
{name: 'FOMO',},
{name: 'ontological design',},
{name: 'flow state',},
{name: 'foreign languages',},
{name: 'streaming on the internet',},
{name: 'video games',},
{name: 'coffee',},
{name: 'crypto currency',},
{name: 'javascript fatigue',},
{name: 'framework wars',},
{name: 'blockchain',},
{name: 'smart contracts',},
{name: 'just emailing me'},
{name: 'ethereum'},
{name: 'university'},
{name: 'engineering software'},
];
const RunningHeader = () => {
const [count, setCount] = useState(0);
setInterval(() => {setCount(c => c + 1)}, 1000);
return (
<header>
<p>{interests[count].name}</p>
</header>
)}
export {RunningHeader};
You need to use setTimeout. setInterval is never being cancelled, so each render adds a new 1s repeating timer. Here's your sandbox fixed in 2 different ways (setTimeout or using useEffect to install the repeating timer on mount):
https://codesandbox.io/s/vy0ww725j0
useEffect with no dependencies [] will act as componentDidMount to mount our interval and we can return a function to get called on unmount, we should clear our internval on unmount to avoid memory leaks.
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(id);
}, []);
Related
So, i'am trying to create async thunk action, to mock data from file to the state.
import { createAsyncThunk, createSlice, PayloadAction } from '#reduxjs/toolkit';
import mocktasks from './mocktasks';
export interface TasksState {
data: Task[];
}
const initialState: TasksState = {
data: [],
};
export const fetchTasks = createAsyncThunk('tasks/fetchTasks', () => mocktasks);
export const tasksSlice = createSlice({
name: 'tasks',
initialState,
reducers: {
setTasks: (state:TasksState, action: PayloadAction<Task[]>) => ({
...state,
data: action.payload,
}),
addTask: (state: TasksState, action: PayloadAction<Task>) => ({
...state,
data: [...state.data, action.payload],
}),
},
extraReducers: {
[fetchTasks.fulfilled.name]: (state, action: PayloadAction<Task[]>) => ({
...state,
data: action.payload,
}),
},
});
export const { setTasks, addTask } = tasksSlice.actions;
export default tasksSlice.reducer;
But there is a strange thing: even though, fetch actions have dispatched, my state hasn't changed.
State and dispatched actions
I thought, that there was an issue with passing the payload to fetchTasks/fulfilled, but Redux devtools shows, that fulfilled has right data in payload, that is obtained from mock file:Action payload
UPD: even though, using dispatch(setTasks(mocktasks)) inside createAsyncThunk works just like i need.
Use builder notation to avoid typescript errors (official recomendation from redux-toolkit docs):
extraReducers: (builder) => {
.addCase(fetchTasks.fulfilled, (state) => ({
...state,
data: action.payload,
}))
},
[fetchTasks.fulfilled.type] should work, as .name seems to always return the string actionCreator.
I need some help with modifying my reducer. I'm using Redux Toolkit and in one of the state slices I've got an object with some grouped settings:
initialState: {
...
userSettings: {mode: 2, subscription: false, setting3: 'text', setting4: 'another text'},
...
}
a reducer I have is:
setUserSettings: (state, action) => {
state.userSettings: action.payload
}
In different parts of a component, I'd update individual settings from the userSettings object:
dispatch(setUserSettings({ mode: 4 }))
in another place:
dispatch(setUserSettings({ setting3: 'some other text'})
How would I modify the reducer to be able to do it? Thanks
Since RTK use immer library underly, you can mutate the state by assigning directly. See Mutating and Returning State
import { configureStore, createSlice } from '#reduxjs/toolkit';
const settingsSlice = createSlice({
name: 'settings',
initialState: {
otherSettings: { ok: true },
userSettings: { mode: 2, subscription: false, setting3: 'text', setting4: 'another text' },
},
reducers: {
setUserSettings: (state, action) => {
state.userSettings = { ...state.userSettings, ...action.payload };
},
},
});
const { setUserSettings } = settingsSlice.actions;
const store = configureStore({ reducer: settingsSlice.reducer });
store.subscribe(() => {
console.log(store.getState());
});
store.dispatch(setUserSettings({ mode: 4 }));
store.dispatch(setUserSettings({ setting3: 'some other text' }));
Output:
{
otherSettings: { ok: true },
userSettings: {
mode: 4,
subscription: false,
setting3: 'text',
setting4: 'another text'
}
}
{
otherSettings: { ok: true },
userSettings: {
mode: 4,
subscription: false,
setting3: 'some other text',
setting4: 'another text'
}
}
change your reducer to
setUserSettings: (state, action) => {state.userSettings={...state.userSettings,action.payload}}
what we did here is making a copy of the old state and then combine it with the new value you need to change
the new key of the object will override the old one
I'm wondering if there is a pattern that allows you to use action creators inside of other action creators. The modifyMassProperty action creator lets you pass any number of actions which are then iterated over and dispatched accordingly. I would very much like to be able to use this method in the getOrbitalBurn action creator since it would be semantically more appealing than using the dispatch method made available by the thunk three times in a row. I'm confident I must either have missed something, or that I'm guilty of getting tangled up in some sort of anti pattern that I concocted during one of my lesser days.
export const modifyMassProperty = (
...massProperties: MassProperty[]
): ThunkAction<void, AppState, void, Action> => (
dispatch: Dispatch<ScenarioActionTypes>
) =>
massProperties.forEach(massProperty =>
dispatch({
type: MODIFY_MASS_PROPERTY,
payload: massProperty
})
);
export const getOrbitalBurn = (
payload: { primary: string; periapsis: number; apoapsis: number },
applyBurn = true
): ThunkAction<void, AppState, void, Action> => (
dispatch: Dispatch<ScenarioActionTypes>,
getState: any
) => {
const scenario = getState().scenario;
const primary = getObjFromArrByKeyValuePair(
scenario.masses,
'name',
payload.primary
);
const orbit = orbitalInsertion(primary, payload, scenario.g);
if (applyBurn) {
const [spacecraft] = scenario.masses;
dispatch({
type: MODIFY_MASS_PROPERTY,
payload: {
name: spacecraft.name,
key: 'vx',
value: orbit.x
}
});
dispatch({
type: MODIFY_MASS_PROPERTY,
payload: {
name: spacecraft.name,
key: 'vy',
value: orbit.y
}
});
dispatch({
type: MODIFY_MASS_PROPERTY,
payload: {
name: spacecraft.name,
key: 'vz',
value: orbit.z
}
});
}
dispatch({
type: MODIFY_SCENARIO_PROPERTY,
payload: {
key: 'orbitalInsertionV',
value: { x: orbit.x, y: orbit.y, z: orbit.z }
}
});
};
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mongo-games')
.then(() => console.log('Now connected to MongoDB!'))
.catch(err => console.error('Something went wrong', err));
const gameSchema = new mongoose.Schema({
title: String,
publisher: String,
tags: [String],
date: {
type: Date,
default: Date.now
},
onSale: Boolean,
price: Number
});
const Game = mongoose.model('Game', gameSchema);
async function saveGame() {
const game = new Game({
title: "The Legend of Zelda: Breath of the Wild",
publisher: "Nintendo",
tags: ["adventure", "action"],
onSale: false,
price: 59.99,
});
const result = await game.save();
console.log(result);
}
saveGame();
My doubt about the code is that : how in this code async/await function is used. What is use of that. Can we not make this without using them.
SOurce : https://vegibit.com/mongoose-crud-tutorial/
I am loading the Redux form with initialValues being passed as props. However, I need to reformat the data so as to fit my form names .. so e.g if the data in initialValues passed as props is {name: 'John', age: '32'}, I want to convert it to {user: {name: 'John', age: '32'}}. How do you achieve it ? Do you write a reducer to accomplish this and if yes then how do you invoke it at the component load ?
Thanks.
You could just do it when you pass in the prop.
const userData = { name: 'John', age: 32 }
...
<MyForm initialValues={{ user: userData }}/>
If you need some bigger changes, you can also pass a function to initialValues:
const getInitialValues = (propValues) => {
const initialValues = {};
// your function to format the values here
return initialValues;
};
#reduxForm(
{
form: 'myForm',
fields: formFields,
},
state => ({
initialValues: getInitialValues(state.userData),
form: state.form
})
)