Swizec Teller - a geek with a hatswizec.com

    Livecoding recap: Blockchain-redux now shares blocks between clients in real-time

    Sunday was fun. We built a thing! πŸŽ‰

    Well… we added a thing to the You Can Use Blockchain To Store And Share UI State proof of concept I've been livecoding on. I'd share a live link with you, but… err… the app broke.

    This is a Livecoding Recap – an almost-weekly post about interesting things discovered while livecoding. Usually shorter than 500 words. Often with pictures. Livecoding happens almost every Sunday at 2pm PDT on multiple channels. You should subscribe to My Youtube channel to catch me live.

    It was working, you see. Then it wasn't. Infinite loop on page load.

    Next time! I promise.

    We did get something working, however. When you dispatch an action on blockchain-redux, the generated block is shared live with all other clients. That sharing still happens via Firebase, so it's not thaaaat impressive, but it's a step in the right direction.

    Swizec Teller published SeniorMindset.com avatarSwizec Teller published SeniorMindset.com@Swizec
    YAY IT WORKS!!!!!1111oneone blockchain-redux is getting useful for realz

    Blocks are shared between clients in real-time. Still backed by Firebase, but baby steps.

    🀘
    Tweet media

    See, you create new benchmark measurements in one browser window, and the other window reacts. Magic πŸ§™β€β™‚οΈ

    Here's how it works πŸ‘‡

    How blockchain-redux shares blocks between clients in real timeat

    Long validation times got you down? Blockchain-redux is all real-time with the firebaseMiddleware. Soon with the WebRTC middleware too, I hope.

    In part that's because there's no real consensus algorithm. Any valid block is accepted to the chain. Longest chain wins by default.

    You may have seen how blockchain initialization works before. We read the whole chain from Firebase and replace the local chain stub.

    Initializing the blockchain from Firebase

    You can read more details about this code in a previous blogpost.

    The part that's new is calling listenForNextBlock after replacing the local chain.

    Listen for the next block

    We have a local chain and want to make sure we catch the next block that shows up. So we fetch the latest index with store.getLastBlock().index, increment by 1, and listen for changes on blockchain/${nextIndex}.

    When that block shows up, we call valueHandler.

    valueHandler then parses the value and calls store.addBlock(), which validates the block fits our chain, and if it does fit, it gets added. If the block makes it to our local chain, then the redux-y stuff kicks in, wakes up all subscribed components, and re-renders happen.

    Completely transparent to your app

    All this real-time sharing is completely invisible to your app. You build your code just like it was any other Redux-based app.

    To initialize the blockchain and render a live count of nodes, you'd do something like this πŸ‘‡

    // App.js
    class App extends Component {
    blockchain = {};
    componentDidMount = async () => {
    const FirebaseApp = firebase.initializeApp({
    apiKey: "",
    databaseURL: "https://thing.firebaseio.com",
    projectId: "thing"
    });
    this.blockchain = await createStore(
    benchmarkReducer,
    firebaseMiddleware(FirebaseApp)
    );
    this.unsubscribe = this.blockchain.subscribe(() => {
    console.log("Hello");
    this.forceUpdate();
    });
    this.forceUpdate();
    };
    componentWillUnmount() {
    this.unsubscribe();
    }
    render() {
    console.log("in render", this.blockchain);
    if (this.blockchain.getState) {
    console.log("Current state", this.blockchain.getState());
    }
    return (
    <div class="App">
    <blockchaincontext class="provider" value={this.blockchain}>
    <introcopy>
    <blockchaincontext class="consumer">
    {blockchain => (
    <benchmarks blockchain={blockchain}>
    )}
    </benchmarks></blockchaincontext>
    <div style={{ padding: "3vh" }}>
    </div>
    );
    }
    }
    </introcopy></blockchaincontext></div>

    Initialize the store in componentDidMount, subscribe to changes, run forceUpdate to get around async issues, unsubscribe on unmount.

    The best way to make this store available to the rest of your app is via the new context API using <Context.Provider value={this.blockchain}>.

    Then inside <IntroCopy />, where you display the node count, you do something like this.

    // IntroCopy.js
    // functional component boilerplate ...
    // ... render stuff
    <blockchaincontext class="consumer">
    {({ getWholeChain = () => [] }) => (
    There are {getWholeChain().length} nodes on the chain
    )}
    </blockchaincontext>
    // ... more other render stuff

    Value passed into render prop is the whole blockchain store. Take out getWholeChain and show the length. You could use getState() to get the latest block value, for example.

    Lots of stuff you can do.

    And to add a new block? Just call dispatch and have a reducer. Blockchain-redux handles the rest :)

    Next steps

    Still have to resolve a few TODO comments around block conflicts. What happens if your network is slow and you add blocks locally that other clients haven't seen and you get blocks from the outside world that conflict? Which do you pick?

    I'm not sure yet.

    Plus I really want to move away from Firebase. That's gonna be fun.

    Join me next Sunday as we continue exploring this experiment.

    Did you enjoy this article?

    Published on April 10th, 2018 in blockchain, Front End, Livecoding, react, redux,

    Learned something new?
    Want to become an expert?

    Here's how it works πŸ‘‡

    Leave your email and I'll send you thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

    Join Swizec's Newsletter

    And get thoughtful letters πŸ’Œ on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

    "Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. πŸ‘Œ"

    ~ Ashish Kumar

    Join 15,161+ engineers just like you already growing their careers with my emails, workshops, books, and courses.

    ⭐️⭐️⭐️⭐️✨
    4.5 stars average rating

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help πŸ‘‰ swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers πŸ‘‰ ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Want to brush up on modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❀️

    Created by Swizec with ❀️