Unconventional React

April 24th

Whoami

Sabin Marcu

Software Engineer at R/GA

Been working in web since '09

React Dev since 2015

React trainer @ JSLeague

We take developers from good to great

WE ARE THE JSLEAGUE

Google React

What will you find?

What we'll be focusing on

  • React development
  • State Managers
  • Server communication
  • Real time data
  • State reconciliation

MobX

GraphQL

React Hooks

Overmind

Styled Components

Linaria

Prisma

Docker

React

Module 1

Module 1

Two types of components:

export default MyComponent 
        extends React.Component {
    state = { counter: 0 }
    render() {
        const { counter } = this.state;
        return (
            <div>
                <h1>Count: {counter}</h1>
                <input
                    value={counter}
                    onChange={(
                        {target:{value}}
                    ) => this.setState(
                        {counter: value}
                    )}
                />
            </div>
        );
    }           
}
export default ({ counter, setCounter }) => (
    <div>
        <h1>Count: {counter}</h1>
        <input
            value={counter}
            onChange={(
                {target:{value}}
            ) => setCounter(
                {counter: value}
            )}
        />
    </div>
);

Module 1

Two types of components:

Stateful Components

Class Components

Smart Components

Etc

Stateless Components

Function Components

Dumb Components

Etc

Module 1

Two types of components:

Stateful Components

Class Components

Smart Components

Etc

Stateless Components

Function Components

Dumb Components

Etc

Module 1

Module 1

Two types of components:

export default MyComponent 
        extends React.Component {
    state = { counter: 0 }
    render() {
        const { counter } = this.state;
        return (
            <div>
                <h1>Count: {counter}</h1>
                <input
                    value={counter}
                    onChange={(
                        {target:{value}}
                    ) => this.setState(
                        {counter: value}
                    )}
                />
            </div>
        );
    }           
}
export default () => {
    const [counter, setCounter] =
        useState(0);
    return (
        <div>
            <h1>Count: {counter}</h1>
            <input
                value={counter}
                onChange={(
                    {target:{value}}
                ) => setCounter(
                    {counter: value}
                )}
            />
        </div>
    );
}

Module 1

Two types of components:

export default MyComponent 
        extends React.Component {
    state = { hasPosts: false }
    componentDidReceiveProps({ posts }) {
        if (this.posts !== posts) {
            this.setState(
                { hasPosts: posts.length > 0 }
            );
        }
    }
    render() {
        const { hasPosts } = this.state;
        const { posts } = this.props;
        return (
            <div>
                {hasPosts 
                    ? posts.map(...)
                    : this.errorMessage();
            </div>
        );
    }           
}
export default ({ posts }) => {
    const [hasPosts, setHasPosts] =
        useState(false);
    useEffect(
        () => setHasPosts(...),
        [posts]
    );
    return (
        <div>
            {hasPosts 
                ? posts.map(...)
                : this.errorMessage();
        </div>
    );
}

Custom Hooks?

Module 1

Module 1

export default (initialData) => {
    const [hasPosts, setHasPosts] = useState(false);
    const [posts, setPosts] = useState(initialData);
    useEffect(
        () => setHasPosts(posts.length > 0),
        [posts]
    );
    const [onChange, setOnChange] = useState(null);
    useEffect(
        () => onChange = ({ target: { value } }) =>
            setPosts(value),
        []
    );
    return { hasPosts, posts, setPosts, onChange };
}

Custom Hooks!

Module 1

export default (initData) => {
    const [id, setId] = useState(initData);
    const [posts, setPosts] = useState([]);
    useEffect(
        () => {
            const subscription = API.subscribe(id, setPosts);
            return () => subscription.unsubscribe();
        },
        [id];
    );
    return { id, posts, setId };
}

Custom Hooks!

State Managers

Module 2

Module 2

Module 2

Module 2

Module 2

Comparison

Server Communication

Module 3

Module 3

Module 3

Module 3

Module 3

Complex example

Get all users

And for each user get all their posts

And for each post get all comments

And for each comment, get its author

All we need to render is all the author's name and id

Module 3

Complex example

Get all users

And for each user get all their posts

And for each post get all comments

And for each comment, get its author

Module 3

Complex example

Get all users (N)

And for each user get all their posts (N*P(N))

And for each post get all comments (N*P(N)*C(P(N)))

And for each comment, get its author (N*P(N)*C(P(N)))

Result: N + N*P(N)(1 + 2 * C(P(N))

Module 3

Complex example

Module 3

query {
    users {
        posts {
            comments {
                author {
                    name
                    id
                }
            }
        }
    }
}

Module 3

GraphQL "Verbs"

Query

Mutation

Subscription

Module 3

mutation {
    createUser(name: "Sabin Marcu", email: "sabinmarcu@gmail.com") {
        id
        isAdmin
    }
}


mutation {
    updateUser( 
        where: { email: "sabinmarcu@gmail.com" }
        data: { isAdmin: true }
    ) {
        id
        isAdmin
    }
}

Module 3

mutation {
    createUser(name: "Sabin Marcu", email: "sabinmarcu@gmail.com") {
        id
        isAdmin
    }
}


subscription {
    user(where: { mutation_in: [CREATED, UPDATED] }) {
        node: {
            id    
            name    
            isAdmin
        }
    }
}

Module 3

Tech Used

  • React Hooks
  • Prisma
  • Apollo Client
  • Mobx
  • Create React App
  • React App Rewired

Thank you!

 

Thank you!

 

Questions?

Made with Slides.com