Introduction

React Hooks are one of those things I decided I would look at later. I’ve read and heard great things about it, so I later is now. I had a component with a form that I thought could be refactored using hooks, so I started with that. Always easier to begin with small steps.

Before

Nothing fancy, we use the material-ui framework to create a Dialog component. Then we have three TextFields ( text inputs ) inside of it:

export default class AddItemPopup extends React.Component {

    constructor(props){
        super(props)
        this.state = {
            name: '',
            quantity: 0,
            unitCost: 0
        }
    }

    handleInputChange = e => {
        const {name, value} = e.target
        this.setState({
            [name]: value
        })
    }

    addItem = () => {
        const {name, quantity, unitCost} = this.state

        if(!name || !quantity || !unitCost) return

        this.props.saveItem(this.state)
    }

    render(){

        const {open, closePopup} = this.props
        const {name, quantity, unitCost} = this.state
        return(
            <Dialog 
                open={open}
                onClose={closePopup}>
                <DialogTitle>Add new item</DialogTitle>
                <DialogContent>
                    <TextField 
                        name='name'
                        label='Item name/Description'
                        onChange={this.handleInputChange}
                        value={name}/>
                    <TextField 
                        name='quantity'
                        label='Quantity'
                        onChange={this.handleInputChange}
                        value={quantity}/>
                    <TextField 
                        name='unitCost'
                        label='Unit Cost'
                        onChange={this.handleInputChange}
                        value={unitCost}/>
                </DialogContent>
                <DialogActions>
                    <Button onClick={closePopup} color="secondary" variant="contained">
                        Cancel
                    </Button>
                    <Button onClick={this.addItem} color="primary" variant="contained">
                            Save
                    </Button>
                </DialogActions>
            </Dialog>
        )
    }
}
            

I saved you the imports at the top of the file, but you got the idea. A class component with a form and a state to keep track of the form inputs’ values. Now, let’s rewrite this component by using the useState hook.

// Import the hook first
import React, {useState} from 'react'

const AddItemPopup = ({
    open, 
    closePopup,
    saveItem
}) => {

    const handleInputChange = e => {
        const {name, value} = e.target
        setValues({...values, [name]: value})
    }

    const addItem = () => {
        const {name, quantity, unitCost} = values

        if(!name || !quantity || !unitCost) return

        saveItem(values)
    }
        // Declare our state variable called values
        // Initialize with our default values

    const [values, setValues] = useState({name: '', quantity: 0, unitCost: 0})
    return(
        <Dialog 
        open={open}
        onClose={closePopup}>
        <DialogTitle>Add new item</DialogTitle>
            <DialogContent>
                <TextField 
                    name='name'
                    label='Item name/Description'
                    onChange={handleInputChange}
                    value={values.name}/>
                <TextField 
                    name='quantity'
                    label='Quantity'
                    onChange={handleInputChange}
                    value={values.quantity}/>
                <TextField 
                    name='unitCost'
                    label='Unit Cost'
                    onChange={handleInputChange}
                    value={values.unitCost}/>
            </DialogContent>
            <DialogActions>
                <Button onClick={closePopup} color="secondary" variant="contained">
                    Cancel
                </Button>
                <Button onClick={addItem} color="primary" variant="contained">
                        Save
                </Button>
            </DialogActions>
        </Dialog>
    )
}

export default AddItemPopup

BOOM! Our component became a function now. What did we do:

  • useState returns two things: the current state ( here as values ) and a function that lets you update it ( here as setValues )
  • useState takes one argument: the initial state.
  • The onChange handler function now uses this setValues function to modify the internal state of the component. As you can see, the values variable is accessible everywhere is the component.

Note: We could have used three different hooks to update each input separately, whatever you think might be more readable to you 😉

Read more

Introduction

You may have heard about closures. You most certainly already use them even if you don’t fully know what they are. Closures require you to know:

Three facts:

Fact One: In Javascript, you can refer to variables defined outside of the current function.

function makeCookies(){
    const secretIngredient = "coconut oil"
    function bake(chocolate){
        return secretIngredient + " and " + chocolate
    }

    return bake("white chocolate")
}

makeCookies() // coconut oil and white chocolate

Here, we can see that the inner function bake can access the variable secretIngredient, even though it was defined in the outer makeCookies function.

Fact Two: Functions can refer to variables defined in outer functions even after those outer functions returned!

Because functions are first-class objects, you can store functions inside variables and call them later on. I’ve talked about higher-order functions in a [https://dev.to/damcosset/higher-order-functions-in-javascript-4j8b](previous article)

function cookiesMaker(){
    const secretIngredient = "coconut oil"
    function bake(chocolate){
        return secretIngredient + " and " + chocolate + " chocolate."
    }

    return bake
}

const func = cookiesMaker() // Storing the function in a variable

Here, cookiesMaker is called and we store the result of that function inside a variable. If you print out the func variable right now, you would see the bake function.

The bake function uses a variable declared outside of the bake function (secretIngredient). The bake function can still remember that variable even if cookiesMaker has already returned.

func("black") // coconut oil and black chocolate.
func("white") // coconut oil and white chocolate.

How is this possible? Well, in Javascript, function values do not just store the code required to execute when they are called. They also store any references to variables they need to execute. Functions like the bake function, who refer to variables declared in their containing scopes are known as closures.

The bake function here keeps track of two variables declared in its containing scope: secretIngredient and chocolate.

When we call bake afterwards, it still remembers those two variables because there were stored in the closure.

A closure can refer to any variable or parameter in its scope. Check this out:

function cookiesBaker(cook){
    return function addSecretIngredient(secretIngredient){
        return function bakeCookie(chocolate){
            return `${cook} cooked a ${secretIngredient} ${chocolate} chocolate cookie.`
        }
    }
}

In this example, the inner function bakeCookie refers to a parameter from the outer cookiesBaker function (cook), a parameter from the outer addSecretIngredient function (secretIngredient) and a parameter from its own scope (chocolate).

const cook = cookiesBaker("Damien")

const secret = cook("peanut butter")

const result = secret("white")
// Damien cooked a peanut butter white chocolate cookie.

Here, we are taking one more step.

We return the inner function addSecretIngredient and store that in a variable. Then, we call that stored function, the result ( bakeCookie ) is stored inside another variable. Finally, we call that function. The final results, as you can see, remembers all the variables stored inside the closure.

We can also use this to make more general-purpose functions.

Let’s say we want to create a function for all cookies baked by Johnny:

const bakedByJohnny = cookiesBaker("Johnny")

bakedByJohnny("coconut oil")("black") // Johnny cooked a coconut oil black chocolate cookie.

bakedByJohnny("")("milk") // Johnny cooked a  milk chocolate cookie.

Notice that instead of declaring a variable and storing the intermediate function inside it. I can call the inner function immediately because bakedByJohnny(“coconut oil”) is returning a function!

Ok, another little example. Let’s create a function for all cookies baked by Sarah with peanut butter:

const bakedBySarahPeanutButter = cookiesBaker("Sarah")("peanut butter")

bakedBySarahPeanutButter("white")
//Sarah cooked a peanut butter white chocolate cookie.

bakedBySarahPeanutButter("black")
// Sarah cooked a peanut butter black chocolate cookie.

bakedBySarahPeanutButter("milk")
// Sarah cooked a peanut butter milk chocolate cookie.

Even though the two functions we created come from the same function definition, they are two distinct objects and both store different variables.

Note: The functions can be anonymous, like so:

let cookiesBaker = function(cook){
    return function(secretIngredient){
        return function(chocolate){
            return `${cook} cooked a ${secretIngredient} ${chocolate} chocolate cookie.`
        }
    }

This code would give the exact same results than before!

Fact Three: Closures can not only remember the variable in their containing scope, they can also update it.

Consider the following example:

const secretIngredient = function(){
    let ingredient = undefined
    return {
        changeIngredient: newIngredient => { ingredient = newIngredient },
        showIngredient: () => ingredient,
        type: () => typeof ingredient
    }
}

This function returns 3 closures. Each method in the object returned refer to a variable defined in the containing scope.

Now, let’s prove that closures can not only read outer variables, they can also update them:

let i = secretIngredient()

i.showIngredient() // undefined
i.type() // undefined

i.changeIngredient("coconut oil")

i.showIngredient() // coconut oil
i.type() // string

Tadaaaaa!

Conclusion

Closures are one of those things that you most likely use very often. You probably didn’t even know about it! Check your code and try to identify closures, get comfortable with them, and use their full powers!

Read more

Introduction

In Javascript, functions are values ( first-class citizens ). This means that they can be assigned to a variable and/or passed as a value.

let random = function(){
    return Math.random()
}

let giveMeRandom = random // assigning random to a variable

This single piece of knowledge allows us to write functional programming in this language. In functional programming, we heavily use higher-order functions.

Higher-order functions?

Higher-order functions are functions that take other functions as arguments or return functions as their results.

Taking an other function as an argument is often referred as a callback function, because it is called back by the higher-order function. This is a concept that Javascript uses a lot.

For example, the map function on arrays is a higher order function. The map function takes a function as an argument.

const double = n => n * 2

[1, 2, 3, 4].map(double) // [ 2, 4, 6, 8 ]

Or, with an anonymous function:

[1, 2, 3, 4].map(function(n){
    return n * 2
}) // [ 2, 4, 6, 8 ]

The map function is one of the many higher-order functions built into the language. sort, reduce, filter, forEach are other examples of higher-order functions built into the language.

Higher-order functions allows you to write simpler and more elegant code. Let’s look at what the code above would look like without such an abstraction. Let’s replace the map function by a loop:

let array = [1, 2, 3, 4]
let newArray = []

for(let i = 0; n < array.length; i++) {
    newArray[i] = array[i] * 2
}

newArray // [ 2, 4, 6, 8 ]

The power of composition

One of the great advantages of using higher order functions when we can is composition.

We can create smaller functions that only take care of one piece of logic. Then, we compose more complex functions by using different smaller functions.

This technique reduces bugs and makes our code easier to read and understand.

By learning to use higher-order functions, you can start writing better code.

Example

Lets try with an example. Assume we have a list of grades from a classroom. Our classroom has 5 girls, 5 boys and each of them has a grade between 0 and 20.

var grades = [
    {name: 'John', grade: 8, sex: 'M'},
    {name: 'Sarah', grade: 12, sex: 'F'},
    {name: 'Bob', grade: 16, sex: 'M'},
    {name: 'Johnny', grade: 2, sex: 'M'},
    {name: 'Ethan', grade: 4, sex: 'M'},
    {name: 'Paula', grade: 18, sex: 'F'},
    {name: 'Donald', grade: 5, sex: 'M'},
    {name: 'Jennifer', grade: 13, sex: 'F'},
    {name: 'Courtney', grade: 15, sex: 'F'},
    {name: 'Jane', grade: 9, sex: 'F'}
]

I want to know a few things about this:

  • The average grade of this classroom
  • The average grade of the boys
  • The average grade of the girls
  • The higher note among the boys
  • The higher note among the girls

We will try to use higher-order functions to get a program that is simple and easy to read. Let’s start by writing simple functions that can work together:

let isBoy = student => student.sex === 'M'

let isGirl = student => student.sex === 'F'

let getBoys = grades => (
    grades.filter(isBoy)
)

let getGirls = grades => (
    grades.filter(isGirl)
)

let average = grades => (
    grades.reduce((acc, curr) => (
        acc + curr.grade
    ), 0) / grades.length
)

let maxGrade = grades => (
    Math.max(...grades.map(student => student.grade))
)

let minGrade = grades => (
    Math.min(...grades.map(student => student.grade))
)

I wrote 7 functions, and each of them has one job, and one job only.

isBoy and isGirl are responsible for checking if one student is a boy or a girl.

getBoys and getGirls are responsible for getting all the boys or girls from the classroom.

maxGrade and minGrade are responsible for getting the greatest and lowest grade in some data.

Finally, average is responsible to calculate the average grade of some data.

Notice that the average function doesn’t know anything about the type of data it’s suppose to process yet. That’s the beauty of composition. We can re-use our code in different places. I can just plug this function with others.

Now, we have what we need to write higher-order functions:

let classroomAverage = average(grades) // 10.2
let boysAverage = average(getBoys(grades)) // 7
let girlsAverage = average(getGirls(grades)) // 13.4
let highestGrade = maxGrade(grades) // 18
let lowestGrade = minGrade(grades) // 2
let highestBoysGrade = maxGrade(getBoys(grades)) // 16
let lowestBoysGrade = minGrade(getBoys(grades)) // 2
let highestGirlsGrade = maxGrade(getGirls(grades)) // 18
let lowestGirlsGrade = minGrade(getGirls(grades)) // 9

Notice that the outer functions, average for example, always take as an input the output from the inner functions. Therefore, the only condition to composition is to make sure that the output and input match.

And because each function is responsible for only one thing, it makes our code that much easier to debug and to test.

Composition rules!

Read more

Introduction

Every year for the last 5 years, Upwork and the Freelancers Union have commissioned a survey in the United States. The goal of these surveys is to have a better understanding of the independent workforce in the country. The study has 4 objectives:

  • Quantify the number of people freelancing in the US and their economic impact.
  • Assess the state of freelancing, especially current demand for freelance services.
  • Gather insights into drivers and barriers impacting freelancing
  • Gauge the outlook for freelancing, especially among millennials as they become the majority of our workforce.

This study is focused on the United States workers. While many of us might not be concerned by the state of freelancing in the US, I believe we can draw some conclusions about the state of freelancing elsewhere as our economies become more intertwined.

Definitions

First, we need to define some terms.

  • Freelancers: Individuals who have engaged in supplemental, temporary, project or contract based work, within the past 12 months.

The study differentiates 5 flavours of freelancers:

  • Diversified workers: People with multiple source of incomes from traditional jobs and freelance work. Someone working part-time in a company and writes code as a freelancer on the side while managing an AirBnB.
  • Independent contractors: Traditional freelancers who do not work for an employer and do freelance, temporary, project or contract based work.
  • Moonlighters: People with a traditional, primary job who also do some freelancing on the side. An corporate-employed accountant working for non-profits on the week-ends for example.
  • Freelance business owners: These freelancers have employees but still consider themselves freelancers.
  • Temporary workers: People with a single employer, client, job or contract project where their employment status is temporary.

What the numbers say

Ok, so now we know what we are talking about. Let’s pull some numbers from this survey that I found interesting. Many of these numbers are compared to the first survey conducted in 2014 to see how freelancing has evolved.

Numbers of freelancers

There are today 56.7 millions freelancers in the US workforce, which represents 35% of the entire workforce. There are 3.7 millions more freelancers compared to 2014.

Diversified workers and independent contractors represent the majority of freelancers, with 31% each. Moonlighters represent 26% of the freelancers workforce, freelance business owners and temporary workers represent 6% each.

Who, What and How?

  • 28% of the US freelancers are full-time freelancers. (17% in 2014)
  • 43% are between 18 and 34 years old. (32% in 2014)
  • 61% started freelancing by choice, not necessity. (53% in 2014)
  • 31% earn more than 75000 $/year. (16% in 2014)
  • 42% freelance less than weekly.
  • 48% see freelancing as a long term thing. (35% in 2014)
  • 74% started in the last 5 years. (70% in 2014)

Training

  • 70% of freelancers participated in training in the last 6 months. (49% among the non-freelancers)

Freelancers look for their training themselves (online forums, books, websites…). Non-freelancers train mostly on the job.

Among the freelancers who graduated from college, 93% found skill related education/training useful to the work they do now. Only 79% of those freelancers found the the college education useful to the work they are doing now.

Most freelancers find the cost of training and skill education too high. (53% vs 33% for non-freelancers)

Many freelancers would benefit from education on essential business skills. For example:

  • 44% of the responders did not agree with the sentence:

I have a good contract that I use for my freelance work.

  • 36% did not agree with the sentence:

I know how to effectively market my skills.

Work and Life

A large majority of freelancers and non-freelancers give the priority to their lifestyle, compared to earnings. However, 84% of full-time freelancers say that their work allow them to have the lifestyle they want. Only 63% say the same thing for non-freelancers.

  • Freelancers enjoy the flexibility and independence they have.
  • The biggest worries for freelancers are income predictability, difficulties in managing their businesses and isolation.
  • Freelancers report they are feeling less stressed, more stimulated and healthier compared than when they have a traditional job.

Freelancing provides opportunities to people unable to work in a traditional job because of health or family issues. 29% of the respondents said a traditional job would not work for them because of health issues. 22% because of a family related issue.

Looking ahead

  • 59% of the freelancers estimate that the freelancing job market has changed compared to 3 years ago. (only 42% said the same thing in 2014).
  • 87% of freelancers think the best days are ahead. (vs 77% in 2014)

A large majority of freelancers (76%) admit that technology makes it easier to find work. Almost 2/3 (65%) think there is a higher demand for freelancers over the past year.

Freelancers find work through multiple sources. Friends and family are the most frequent source with 46%, social media with 40%, previous clients with 38% and professional contacts with 36%. These are the four more frequent ways freelancers will find work nowadays.

  • A good majority of freelancers find work online (64% vs 42% in 2014)
  • 82% of non-freelancers admit they would be open to freelancing on the side to make extra money.
  • Among the freelancers who left a traditional job to freelance, 60% earn more money. Among those 60%, 77% took less than a year to have an superior income than their former job.
  • Half the freelancers today say they wouldn’t go back to a traditional job, no matter how much money they were offered.

Conclusion and Sources

Freelancers are already a huge part of the workforce. They will most likely become the more important part of the workers in the future. This series of studies might help us understand what freelancers are expecting from our society, where they come from and how they can help our economies.

Below, you will find the links to the slides for the surveys from year 2014 to 2018. In each, there is a section about politics. Freelancers might very well become a crucial part of the electorate in the future.

Sources:

2018 Survey
2017 Survey
2016 Survey
2015 Survey
2014 Survey

Read more


Introduction

Some changes in my professional life made me rethink the way I was freelancing and looking at/for clients. I started reading a book called the Freelancer’s Bible, written by Sara Horowitz. There are a lot of useful informations in there, even if the book is not about our field in particular.

Anyway, in this book, the author talks about 4 levels of clients. These are 4 levels that you should have in your portfolio. Balance these levels and you won’t have too much trouble getting work (and money) in the future.

The freelance portfolio

The author compares this portfolio to a financial portfolio. To protect yourself from the market’s volatility, it’s a good idea to diversify your holdings. If one of your asset ( or client ) disappears, you have other options at your disposal to earn money. Your portfolio must also be balanced so you meet some goals:

  • Have enough good clients. What’s a good client? Someone who pays well and/or can advance your career. Make sure you don’t have too few and not more than you can handle.
  • Bring enough steady income to prepare for rainy days.
  • Meet your total income goals.

Depending on where you stand, you might have to rebalance your portfolio.

The levels

So, the author describes 4 levels of clients, which I will try to describe the best I can.

  • Level 1: The Blue Chips
  • Level 2: Growth Investments
  • Level 3: One-Shots and Long Shots
  • Level 4: New Ventures and Growth

The Blue Chips

The Blue Chips are the core of your freelance portfolio. They provide you a regular source of income. The buy-and-hold investments. They are usually your most important clients. You have a deep relationship with them. You might even get referrals!

But, there are some challenges with the Blue Chips clients. If the project is awful, or the people are, you might not have the luxury to leave until you find a way to replace the lost income. Because Blue Chips can also disappear, it’s a good idea to have more than one client like these in your portfolio. Be also careful about the boundaries with Blue Chips, you are a freelancer, not an employee. Make sure they understand that.

Growth Investments

Called the Blue Chip Incubator in the book. These are clients you’ll get from referrals, other freelancers or your own prospecting. Level 2 is about networking. By having a solid Level 2, you’ll stabilise your career.

You are in control of Level 2. You are looking for opportunities and try to turn some prospects into Blue Chips clients. You decide which type of projects and clients Level 2 will bring you.

The challenging part about Level 2 is finding a good price for yourself. Too low and you’ll get stuck in low-paying gigs that takes too much time. Too high and some interesting prospects can’t afford you. Find a balance.

One-Shots and Long Shots

These gigs are about filling time or income gaps. You need money right now. You don’t have much time to network or you know you’ll be a few weeks without work, this is where you go. You are looking at job boards or websites like Upwork.

There are a ton of opportunities in these places. No networking is needed because the prospects are waiting to hear from you. These platforms also ensure payments, so you won’t have to chase your check.

However, you will be hundreds of freelancers applying for the same gig. The pricing is extremely variable. Some platforms might even have a way to track the number of hours you are spending on a project or check your progress… Talk about the freelancer’s freedom…

Anyway, keep Level 3 for what it is. Quick money, short-term gigs and fast experience. You need money, you do what you gotta do. But you shouldn’t have all your portfolio here.

New Ventures and Growth

This is the most speculative part of your freelance portfolio. It could also be the most exciting. Here, you are creating services or products that will bring income in the long-term. You could work with other freelancers on a project. You could write a book. You could think about teaching…

Level 4 needs to be planned. It stays on your radar. It shouldn’t eat away too much time for the other parts of the portfolio that are bringing income now.

Conclusion

You now know the 4 different levels of clients you can have in your portfolio. As a freelancer, how does your portfolio looks like? Do you think it should/could be more balanced? Do you believe there are other types of level?

Read more