Code Monkey home page Code Monkey logo

Comments (3)

kbrsh avatar kbrsh commented on June 12, 2024 1

@mrEvgenX Ah I see, you're right, this is lacking too much elegance for my liking as well. First off, I'd like to thank you for both creating and extending this issue — it has pushed me to rethink of how Moon's functional approach can be used more practically. This is a perfect candidate for a new app structure and API I've been conceptualizing for the past few weeks. I tweeted a code sample that used this approach a few days ago (except with a React driver), so I'm excited to see how it can be applied here!

Basically, you structure an application with two transformations: input to state and state to output. Check this solution out:

const { div, p, button }
	= Moon.view.m;

const go = page => input => main({
	...input.data,
	page
});

const increment = input => 
	input.data.page === "index" ?
		main({
			...input.data,
			counter: input.data.counter + 1
		}) :
		main(input.data);

const pageIndex = state => ({
	data: state,
	time: {3000: increment},
	view: (
		<div>
			<p>{state.counter}</p>
			<button @click=(go("counted"))>Create</button>
		</div>
	)
});

const pageCounted = state => ({
	data: state,
	view: (
		<div>
			<p>Result: {state.counter}</p>
			<button @click=(go("thanks"))>Get Thanks</button>
		</div>
	)
});

const pageThanks = state => ({
	data: state,
	view: (
		<div>
			<p>Thank you</p>
		</div>
	)
});

const main = state => {
	switch (state.page) {
		case "index": return pageIndex(state);
		case "counted": return pageCounted(state);
		case "thanks": return pageThanks(state);
	}
};

Moon.use({
	data: Moon.data.driver,
  	time: Moon.time.driver,
	view: Moon.view.driver("#root")
});

Moon.run(input => main({
	page: "index",
	counter: 0
}));

Playground

In this case, any event handlers transform from input to state and then hand it off to main, which transforms state back into output. With this, event handlers and the initial run are responsible for the dirty work of converting inputs to a state that reflects an application much more accurately. Then, the main function can transform it back to driver outputs.

As I work on a few changes to the API and codebase structure, I'll be adding this methodology to the docs. If you'd like, you can try adding documentation; the code is on the gh-pages branch.

Let me know what you think!

from moon.

kbrsh avatar kbrsh commented on June 12, 2024

This is a good exercise. Thanks for posting it, I think some revisions I have of Moon's API can help the ergonomics of things like this. The main problem is that tick outputs to a driver which sets a timeout, so setting time: undefined won't cancel any previous timeouts already set. The logic will have to go into tick or another function. Here's a quick way I was able to get it working:

const { div, p, button }
	= Moon.view.m;

const goSeeingCounted = ({ data }) => ({
	data: {...data, isTicking: false},
	view: <viewSeeCounted counter=data.counter/>
});

const viewCounter = ({ counter }) => (
	<div>
		<p>{counter}</p>
		<button @click=goSeeingCounted>Create</button>
	</div>
);

const viewSeeCounted = ({ counter }) => (
	<div>
		<p>Result: {counter}</p>
	</div>
);

const tick = ({data}) => {
	const newData = {...data, counter: data.counter + 1};
	return {
		data: newData,
		time: {1000: main},
		view: <viewCounter counter=newData.counter/>
	}
};

const main = (input) => {
  	const data = input.data === undefined ?
		{counter: 0, isTicking: true} :
		input.data;
  	const newInput = {...input, data};
	return data.isTicking ? tick(newInput) : goSeeingCounted(newInput);
};

Moon.use({
	data: Moon.data.driver,
  	time: Moon.time.driver,
	view: Moon.view.driver("#root")
});

Moon.run(main);

Playground

from moon.

mrEvgenX avatar mrEvgenX commented on June 12, 2024

Thanks for your solution. It look quite well and works nice. But another problem begins if I increase delay up to, say, 3 seconds and add the next step. Please, take a look at an example in playground. Try to click "Create" and "Get thanks" whithin 3 seconds.

I think I'm able to fix it now. But I'm sure, a solution for this is gonna look not so nice and pretty. What do you think?

And I'm sure it should be mentioned somewhere on moonjs.org, may be in guide time or examples. May be I can help with it, are moonjs.org's sources available for PRs?

from moon.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.