Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 19:30
    jakovljevic-mladen synchronize #7176
  • 19:29
    devversion edited #7130
  • 19:28
    devversion edited #7130
  • 19:25
    jakovljevic-mladen synchronize #7176
  • 19:04
    jakovljevic-mladen opened #7176
  • 10:08
    raveclassic review_requested #7172
  • 10:07
    raveclassic edited #7172
  • 10:06
    raveclassic commented #7172
  • 10:01
    raveclassic synchronize #7172
  • 02:05
    benlesh synchronize #7167
  • Jan 27 08:12
    jakovljevic-mladen commented #7167
  • Jan 27 04:00
    benlesh commented #7167
  • Jan 26 23:56

    benlesh on master

    docs(readme): fix number versio… (compare)

  • Jan 26 23:56
    benlesh commented #7174
  • Jan 26 23:56
    benlesh closed #7174
  • Jan 26 22:38
    fabricio opened #7174
  • Jan 26 08:30

    jakovljevic-mladen on 7.x

    docs(exhaustAll): fix marble di… (compare)

  • Jan 25 22:44
    raveclassic commented #7172
  • Jan 25 22:43
    raveclassic commented #7172
  • Jan 25 22:41
    demensky opened #7173
Derek
@derekkite
Not certain how react works, but the handleMousDown() function is called on a mouse down event, would the fromEvent (..., 'mousedown') see that event? It is called after the initiating event.
Steve Ebenezer Paul
@steveebenezer
I tried using this in the useEffect Hook in react, but the ele is draggable only once, also the 2nd takeUntil when removed the ele is draggable but the ele get's jumpy, is there a different way to handle these in react?
Matt Palmer
@MattSPalmer
Instead of setting up observables in the mousedown handler, I'd suggest using the ref to create all the observables (including mousedown) in a useMemo(), then subscribing in a useEffect.
function Draggable({ id, dispatch, pos, label, size }) {
  const draggableRef = createRef();
  const [coords, setCoords] = useState(pos);

  const [labelPos, setLabelPos] = useState({
    x: pos.x + size.w / 2,
    y: pos.y + size.h / 2
  });

  useEffect(
    () => {
      setLabelPos({
        x: coords.x + size.w / 2,
        y: coords.y + size.h / 2
      });
      dispatch({
        type: 'UPDATE_BOX_POS',
        id: id,
        x: coords.x,
        y: coords.y
      });
    },
    [dispatch, coords, size, id]
  );

  // NOTE - Using useMemo here for simplicity's sake, but you may want to use a
  // combination of useEffect and useRef instead, as useMemo can recalculate
  // values at will.
  const drag$ = useMemo(
    () => {
      if (!draggableRef.current) return EMPTY;
      const animationFrame$ = interval(0, animationFrameScheduler);
      const dragTarget = draggableRef.current;

      // Using tap means the side effects are handled automatically as part of
      // a single subscription to the "mousedrag$" stream.
      const mousedown$ = fromEvent(dragTarget, 'mousedown').pipe(
        tap(() => dispatch({ type: 'SELECT_BOX', id: id, selected: true }))
      );
      const mouseup$ = fromEvent(dragTarget, 'mouseup').pipe(
        tap(() => {
          // if (!selected) { return; }
          console.log('----- drag end -----');
          dispatch({ type: 'SELECT_BOX', id: id, selected: false });
        }),
        share()
      );
      const mousemove$ = fromEvent(document, 'mousemove');

      const mousedrag$ = mousedown$.pipe(
        flatMap((md) => {
          const dx = md.offsetX - coords.x;
          const dy = md.offsetY - coords.y;
          return animationFrame$.pipe(
            withLatestFrom(mousemove$, (_, p) => {
              p.preventDefault();
              return p;
            }),
            scan(lerp(0.5)),
            map((p) => ({
              x: p.x - dx,
              y: p.y - dy
            })),
            // What does this do?
            takeUntil(mouseup$.pipe(last()))
          );
        }),
        takeUntil(mouseup$),
        tap(({ x, y }) => {
          setCoords({ x, y });
        })
      );
      return mousedrag$;
    },
    [draggableRef.current, dispatch, setCoords]
  );

  useEffect(
    () => {
      const subscription = drag$.subscribe();
      return () => subscription.unsubscribe();
    },
    [drag$]
  );

  return (
    <g className="ele" ref={draggableRef}>
      <rect
        width={size.w}
        height={size.h}
        x={coords.x}
        y={coords.y}
        rx="5"
        ry="5"
        fill="#fff"
        stroke={'#111' /*isSelected ? "#666" : "#111"*/}
      />
      <text
        x={labelPos.x}
        y={labelPos.y}
        textAnchor="middle"
        alignmentBaseline="central"
      >
        Hello
      </text>
    </g>
  );
}

export default Draggable;
1 reply
connor-odoherty
@connor-odoherty

I often find myself writing Observable chains with empty success handlers like this:

            concat(this.tripExpenseAccessor.destroyExpense(expense), this.hydrate()).subscribe(
              (success) => {},
              (error) => {
                this.rollbar.error(error);
              }
            );

This feels like a code smell. Is the best practice to use catchError instead like below?

            concat(this.tripExpenseAccessor.destroyExpense(expense), this.hydrate()).pipe(
              catchError((error) => {
                this.rollbar.error(error);
                return of({});
              })
            ).subscribe();
Jorrit
@jorrit-wehelp
@connor-odoherty .subscribe({error: err => ...})
it accepts a partial observer
Lodewijk Wensveen
@lwensveen
I have this piece of code, now I need a cancelling effect like switchmap, any idea?
    this.onDispatchChanges.pipe(
      debounceTime(600),
      distinctUntilChanged(),
    ).subscribe(dateChanges => {
      this.dispatchChanges(dateChanges);
    });
Jorrit
@jorrit-wehelp
so... use switchMap...? ;p
not sure what dispatchChanges does, but does look a bit suspicious. Whatever is does should probably just be directly chained off onDispatchChange obs :/
Lodewijk Wensveen
@lwensveen
It does all kinds of calculations with dates and stuff
I don't understand how to do this
Jorrit
@jorrit-wehelp
make the calculation observable, then .switchMap(dateChanges => dispatchChangesAsObservable(dateChanges) ?
Lodewijk Wensveen
@lwensveen
Nah my editor has some weird issue where it tries to force switchmap as a async function
Dorus
@Dorus
Rxjs is for async actions, not for canceling sync calculations
And you already have debouceTime so you already cancel quit succeeding requests
Lodewijk Wensveen
@lwensveen
It's a bit weird
there's this subject that's being nexted from a input
    this.onChangeHourChanged.pipe(
      distinctUntilChanged(),
      takeUntil(this.destroyed$),
    ).subscribe((hour) => {
      const type = DateTimeType[this.dateTimeType];
      console.log('HourChanged');

      this.currentDateTime.set({
        hour,
      });

      this.time = this.setTime(this.dateFilterValidatorService.setDate(type, this.currentDateTime));
      this.writeValue(this.time);
    });
then it calls this setDate from the service
this.onDispatchChanges.next(changes);

    this.onDispatchChanges.pipe(
      debounceTime(600),
      distinctUntilChanged(),
    ).subscribe(dateChanges => {
      this.dispatchChanges(dateChanges);
    });
Then in there it does this
I supppose it's being done like this so you can have the debounce?
Dorus
@Dorus
WHy do you subscribe after you next?
Is it a replay/behavior subject?
Lodewijk Wensveen
@lwensveen
nah it's just a regular subject
Dorus
@Dorus
You should only subscribe once and do it before you call next usually.
Ok regualar subject will forget about your next call, so that subscribe will not receive it. Just saying
common mistake (and a reason why you should avoid subjects)
Lodewijk Wensveen
@lwensveen
But then it will never receive data?
Dorus
@Dorus
yes it will only receive data that has been emitted from the subject after you subscribe.
Lodewijk Wensveen
@lwensveen
Which is none? :S
Dorus
@Dorus
Anyway this is unrelated to your cancel question (that i still do not quite understand)
Lodewijk Wensveen
@lwensveen
rxjs always works great till it doesn't
If I log inside that subscribe it logs like 3 times
at random really
Dorus
@Dorus
then you are calling the subject from somewhere
Lodewijk Wensveen
@lwensveen
Seems it doesn't clear it or something
Dorus
@Dorus
you could add tap() with a log in a few places to see wht's going trough it at each step
Lodewijk Wensveen
@lwensveen
But anyways this is too confusing for me, normally it makes sense but this is really strange, so I might just rewrite it using promises or something
Yeah that's what I did but see ^
Anyways it's still not clear to me what you meant with the next and the pipe?
A subject needs data, so you need to call next, or init it as a behavioursubject?
Dorus
@Dorus
A subject just forwards the next call to any current subscribers when you call next on it.
Lodewijk Wensveen
@lwensveen
Yes correct
Then how would I do that pipe etc without calling next?
Dorus
@Dorus
A subject is a hot primitive, it's both a observer and observable and it contains live data, other than say a cold observable like of(changes) that only holds one value and replays it each time you subscribe. Creating a new execution context each time you do.
If you use a subject, you should subscribe first and call next on it later
It's like, turn on the radio before you broadcase something, else you wont hear it.
Lodewijk Wensveen
@lwensveen
Ahh like that
Dorus
@Dorus
It's the biggest difference between promises and observable. Promises are eager, observable lazy. So with observable nothing happens till you subscribe.