Search code examples
reactjsreactivekefir.jscalmm

How should I trigger an XHR on component MouseClick using CalmmJS and React?


What I want is to trigger an XHR.perform onMouseClick, using CalmmJS and React - I'm trying the following code, unnecessary parts redacted:

const getResults = someArg => XHR.perform({
    timeout: 60 * 1000,
    responseType: 'json',
    method: 'POST',
    url: U.string`/api/${ facet }/end-point/`,
    body: U.stringify( someArg )
});
...
<SomeElement
    ...
    onMouseClick={ U.ifElse(
            shouldMakeXHR, /* Atom that runs its own debounced XHR checks, then
                              runs it through an R.equals to see if the result
                              is acceptable - result is either true or false */
            _ => getResults( someArg ),
            R.identity //as no-op
    ) }
/>

Currently I'm just trying to trigger the network request, not do anything with the result. Instead the XHR.perform just gets swallowed without a trace. What am I doing wrong?

PS: Please could someone tag my post with karet or karet.util, as I am unable to create tags. Thanks for any help!


Solution

  • This is another basic one that I just kept banging my head against for some reason.

    The answer is to not use a regular function, but to take advantage of the karet.util library and U.doPush a value to a U.bus() stream. The official CalmmJS documentation actually points you to a really clear and simple example demonstrating this behaviour. U.doSet a value to a regular U.atom(), although I'm starting to think there must be a better way...will update this answer if I find it.

    There is a better way! Straight from Vesa Karvonen/@polytypic himself:

    const requestsBus = U.bus()
    
    const xhrProperty = XHR.perform(U.toProperty(requestsBus)) 
    
    <button
      onClick={U.doPush(requestsBus, {
            timeout: 60 * 1000,
            responseType: 'json',
            method: 'POST',
            url: U.string`/api/${ facet }/end-point/`,
            body: U.stringify( someArg )
    })}>
      Request!
    </button>
    

    Here's the original almost-working code, for posterity - DO NOT USE THE CODE BELOW THIS LINE - SEE ABOVE

    const mouseClick = U.atom( false );
    const makeRequest = someArg => XHR.perform({
    timeout: 60 * 1000,
    responseType: 'json',
    method: 'POST',
    url: U.string`/api/${ facet }/end-point/`,
    body: U.stringify( someArg )
    });
    const getResponse = U.when( mouseClick,
        XHR.responseFull( makeRequest( someArg ) );
    ...
    <p>{ U.stringify( getResponse ) }</p>
    <SomeElement
    ...
        onClick={ U.ifElse(
            shouldMakeXHR, /* Atom that runs its own debounced XHR checks, then
                              runs it through an R.equals to see if the result
                              is acceptable - result is either true or false */
            U.doPush( mouseClick, true ),
            R.identity //as no-op
    ) }
    />
    

    Note that this will continue to make XHR post requests whenever someArg changes after the first mouse click.