# Brainstorming: Use Effect
```typescript=
import {invalidate, useState} from '@builder.io/qwik';
interface WeatherState {
temp: number;
}
interface WeatherProps {
city: string;
}
function fetchWeather(props: WeatherProps, state: WeatherState) {
const data = await(await(fetch(`.../${props.city}`)).json());
state.temp = data.temp;
}
function IntervalUpdate(this: WeatherState, props: WeatherProps): number {
let intervalId = setInterval(fetchWeather, 1000, props, this);
return [intervalId, () => clearInterval(intervalId)];
}
function useWeather(props: WeatherProps) {
const state = useState<WeatherState>({temp: null});
onResume(() => useTransient(state, IntervalUpdate, props));
onHalt(() => releaseTransient(state, IntervalUpdate));
useWatcher(() => fetchWeather(props, state), [props]);
return state;
}
const Weather = qComponent((props: {city: string}) => {
const weatherProps = useState({city: props.city});
const weather = useWeather(weatherProps);
return () => (
<div>
<span>{weatherProps.city}</span>
<span>{weather.temp}</span>
<button on:click={() => invalidate(weatherProps) }>refresh</button>
</div>
);
});
```
```typescript=
export const x = (props: {city: string}) => {
const weatherProps = useState({city: props.city});
const weather = useWeather(weatherProps);
onRender( () => (
<div>
<span>{weatherProps.city}</span>
<span>{weather.temp}</span>
<button on:click={() => invalidate(weatherProps) }>refresh</button>
</div>
));
}
const Weather = qComponent(x);
// const Weather = qComponent(qHook('./chunk#x'));
function genericRendering(x) {
return onRender(() => <span>{x}</span>)
// const export s1 = () => <span>{x}</span>;
// return onRender(qHook('./chunk#s1'))
}
const MyComp = qComponent(() => {
return genericRendering('abc')
});
```
```typescript=
const MyComp = qComponent(async (proprs: {}) => {
const result = await HUGE_LIBRARY_NODE();
const state = useState(result.value);
onRender(() => <span>{state}</span>);
return () => <span>{state}</span>;
})
```
transform to:
```typescript=
const s1 = () => {
const [state] = useClosure();
return <span>...</span>;
}
const s2 = () => {
const [state] = useClosure();
return <span>...</span>;
}
const s3 = (proprs: {}) => {
const result = await HUGE_LIBRARY_NODE();
const state = useState(result.value);
onRender(qHook(`./chunk#s1`, [state])); // <== consider not supporting
return qHook(`./chunk#s2`, [state]); // <=== Preffered
}
const MyComp = qComponent(qHook('./chunk#s3'));
const Weather = qComponent((props: {}) => {
onMount: () => {
const weatherProps = useState({city: props.city});
const weather = useWeather(weatherProps);
}
onRender: () => {
<div>
<span>{weatherProps.city}</span>
<span>{weather.temp}</span>
<button on:click={() => invalidate(weatherProps) }>refresh</button>
</div>
}
onRender(() => (
<div>
<span>{weatherProps.city}</span>
<span>{weather.temp}</span>
<button on:click={() => invalidate(weatherProps) }>refresh</button>
</div>
));
});
```
## Clock use case:
```typescript=
import {useInterval} from '@builder.io/qwik';
export Clock = qComponent((props: {}) => {
const time = useInterval(qFn(() => ({value: new Date()}), 1000));
onRender(() => <span>{time.value}</span>);
});
```
# `useInterval`
```typescript=
import {cleanupTuple, useState} from '@builder.io/qwik';
export function IntervalUpdate(fn: QFunction, returnValue: {}, delay: number) {
let intervalId = setInterval(() => assign(returnValue, await fn.invoke()), delay);
return cleanupTuple([intervalId, () => clearInterval(intervalId)]);
}
export function useInterval(fn: QFunction, delay: number) {
const state = useState();
onResume(() => useTransient(state, IntervalUpdate, fn, state, delay));
onHalt(() => releaseTransient(state, IntervalUpdate));
return state;
}
```
## Refresh use-case:
```typescript=
export MyCmp = qComponent((props: {a, b}) => {
const state = useState({ value: 0});
useEffect((a, b) => {
state.value = a + b;
}, [props.a, props.b]);
onRender(() => <span>{stock}</span>)
});
```
Problem:
- By listing dependencies explicitly there is no way to rerun the reading of the deps. We don't know that we will have to re-run when `props.a` or `props.b` changes.
```typescript=
export MyCmp = qComponent((props: {a, b}) => {
const state = useState({ value: 0});
const c = foo();
useEffect(() => state.value = props.a + props.b + c.bar);
useEffect(($) => state.value = $(props).a + $(props).b + $(c).bar);
// export const effectSymbol = () => {
// const [state] = getClosure();
// return state.value = props.a + props.b;
// }
// useEffect(qHook('.chunk#effectSymbol{*state}|*props.a.b'))
onRender(($) => (<span>{$(stock).price}</span>));
});
```
Problem:
- By not listing dependencies explicitly we can use proxy to figure out what we need to listen on. But the `useEffect` function must be synchronous as we will not be able to tell async reads with which `useEffect` they go with!
- As of right now the tracking system is object level only (not prop level). Do we care?
```htmlembedded=
<div
q:render="./path#renderSymbol{*state}|*state"
q:effect="./path#effectSymbol{*state}|*props.propA.propB,*otherState.propC"
q:obj="abc xyz"
>
</div>
```
```typescript=
export function useMemo(fn: QFunction, deps: QSerializable[]): QObject {
let value;
useEffect((fn) => value = await fn.invoke(), fn);
return value;
}
```
```typescript=
export const MyComp = qComponent(() => {
const state = useState({count:0})
const interval = useInterval(1000);
useEffect(
(timestamp: number) => state.count++,
[propOf(interval, 'timestamp')]
);
// q:effect="./chunk#symbol{state}|interval.timestamp"
onRender(() => <span>{state}</span>)
})
```
---
# Manu's `useInterval`
```typescript=
import {cleanupTuple} from '@builder.io/qwik';
export function IntervalUpdate(fn: QFunction, delay: number) {
let intervalId = setInterval(() => await fn.invoke(), delay);
return cleanupTuple([intervalId, () => clearInterval(intervalId)]);
}
document.load => whatever
function idealUseInterval(fn, delay) {
useEffect(() => {
let thing = setInterval(() => fn(), delay);
return () => {
clearInterval(thing);
}
}, [fn, delay]);
}
export function useInterval(fn: QFunction, delay: number) {
const value = useState({count: 0});
onResume(() => useTransient(value, IntervalUpdate, fn, delay));
onHalt(() => releaseTransient(value, IntervalUpdate));
return value;
}
```
## Clock use case 2
```typescript=
import {useInterval} from '@builder.io/qwik';
export function useClockWithFunction = (fn, tickTime) => {
const state = useState({count: 0});
onResume(() => {
useEffect(() => {
const timer = setInterval(()=>{
fn();
}, tickTime);
return () => clearInterval(timer);
});
})
}
export ClockImplemention = (props: {}) => {
useClockWithFunction
// 0, Unserializable
onMount(() => {
setTimeout()
});
};
import css from './cmp.css'
export Clock = qComponent((props: {}) => {
withTag('bar');
return <Foo>{state}</Foo>);
});
/** @qwik */
function Foo() {
return <button></button>
}
function genericRender(state) {
return () => {
}
}
```
---
```typescript=
export const x = () => {
return foo();
};
export MyComp = qComponent(x)
export foo() {
return () => <span></span>
}
```
- using onRender()
- qComponent takes an arrow function
```typescript=
import {expr, expr2} from './bar'
MARKER_FN(expr())
// export const s1 = expr()
// MARKER_FN(qHook('./chunk/s1'))
<div on:___={expr2}>
// export cnst s2 = expr2
// <div on:__={qHook('./chunk#s2')}
```