Skip to content

Releases: yunusparvezkhan/adprava

Version 4 Anaros 🍍

24 Jun 11:23
Compare
Choose a tag to compare

The version 4 of the Adprava app has a new page CounterPage, which is a basic counter component, famous in ReactJS World. The aim of this page is learning and practicing Reducer functions in ReactJS. In addition to that this page is also a practice for custom hooks, as all the logics behind the counter component is migrated to a reusable custom hook.

Reducer Functions in ReactJS

Introduction :-

Reducer is an alternative to the useState hook in React. Reducer is also a hook and imported as useReducer from react. This hook is a better state manegement system for larger applications, as using simple useState in larger applications can be complicated and confusing due to its "separate declaration for separate state" theory. To address this issue, useReducer gives a distinguish feature of initiating all the states inside a object, passed to useReducer()'s second argument. Now, although the state updation process may seem like overwhelming, it is actually more descriptive and formal in my sense. To update a state, the specific function dispatch() is to be called, with an value, which then goes to a defined function, which the developer then decide what to do with that value. These things may go over the head of many people, but we will discuss in details on what and how to use useReducer.

Use of the useState hook

We use useState hook to create states like class components are used to have. To declare a state we write on the top of the code inside the function component,

    const [exampleState, setExampleState] = useState('The Default Value and default Data Type');

So the entire component may look something like,

const App = () => {
    const [exampleState, setExampleState] = useState('The Default Value and default Data Type');
    // More code
    // More code
    return(
        <div>
            {exampleState}
        </div>
    );
};

The first value exampeState is the variable for the state. The second value setExampleState is the setter function for that state. You must have noticed that to call the state, we do not need to mention this.state.exampleState, rather we directly called the state by exampleState, as like calling a variable. Then the setter function can be also directly called as

setExampleState("New Value");

Declaration of useReducer hook

The declaration of the useReducer hook is much similar to the useState hook. To declare useReducer hook, we write on the top of the code inside the functional component,

const [state, dispatch] = useReducer(reducer, {
    state1:'Default value of state1',
    state2:'Default value of state2',
    state3:5,
})

There is nothing special about the terms state and dispatch, but as international convention almost every developer uses these default terms. Then inside the useReducer() function call, the first argument is a function, that should be declared somewhere in the file, and the second argument is the entire state. It definitely can be an object or any other data types. The variable state is reference to the entire state, declared in the second argument of the useReducer() function call.

Accessing the useReducer state

To access the state created by using the useReducer hook, the varibale assinged to it, can be used

Example - The component with the state declaration by using useReducer hook in the previous point may look like,

import React, { useReducer } from "react";

export default const App = () => {
    const [state, dispatch] = useReducer(reducer, {
        state1:'Default value of state1',
        state2:'Default value of state2',
        state3:5,
    })

    //  Some more code

    return(
        <div>Some JSX</div>
    )
}

Now here inside the return() function, if we want to access any of the state values, we may write,

return(
    <div>
        State 1 --> {state.state1}
        State 2 --> {state.state2}
        State 3 --> {state.state3}
    </div>
)

And this will give us back the values of corresponding states.

Updating the useReducer state

Remember we have passed reference of a function reducer as the first argument of useReducer() function call in the useReducer declaration. That function need to be initiated somewhere in our file. By convention developers feel it right to declare that function at the top of the file, before the component function. So now, with the reducer() declaration our file may look something like,

import React, { useReducer } from "react";

const reducer = () => {
    // Some logic to handle state dispatch
}

export default const App = () => {
    // useReducer declaration
    const [state, dispatch] = useReducer(reducer, {
        state1:'Default value of state1',
        state2:'Default value of state2',
        state3:5,
    })

    //  Some more code

    return(
        <div>
            State 1 --> {state.state1}
            State 2 --> {state.state2}
            State 3 --> {state.state3}
        </div>
    )
}

To update the state, the dispatch() function is to be used. And the value passed in the first argument of the dispatch() function will be recieved in the second argument of the reducer() function. In total the reducer() function recieves two arguments, state and action. Whenever we call dispatch(), it calls the reducer(). Then whatever the reducer() function will return, would be the new state. So, we can dispatch an object like,

{
    type:"UPDATE_STATE1",
    payload:"The New Value",
}

for updation of state1, now we have to recieve this in the reducer() and return a new state.

import React, { useReducer } from "react";

const reducer = (state, action) => {
    // Some logic to handle state dispatch
    // checking dispatch types before returning new state
    if (action.type === "UPDATE_STATE1") {
        return {
            ...state,
            state1:action.payload,
        };
    };
};

export default const App = () => {
    // useReducer declaration
    const [state, dispatch] = useReducer(reducer, {
        state1:'Default value of state1',
        state2:'Default value of state2',
        state3:5,
    })

    const handleCSTabc = () => {
        // Dispatching an object with a type prop
        dispatch({
            type:"UPDATE_STATE1",
            payload:"ABC",
        })
    }

    return(
        <div>
            State 1 --> {state.state1}
            State 2 --> {state.state2}
            State 3 --> {state.state3}

            <button onclick={handleCSTabc} >Change State1 to abc</button>
        </div>
    )
}

As it can be seen in the examle code, that we may dispatch an object with a predefined type property, and then check the type in the reducer() function before returning a new state. And this process can be continued and further nested for more states, and more updates.

Full Changelog: v3...v4

Version 3 Tormuj 🍉

18 Jun 18:16
Compare
Choose a tag to compare

The version 3, Tormuj has a new page TablePage. This page demonstrates two new components Table and SortableTable. These components are for rendering dynamic Tables by passing data as props.

TablePage

The Table component

Table is a component to render a decent table. This table is dynamic and controlled by a dataset, in a other file or in a backend server. The Table component recieves 3 props as data, config and KeyFn. The Table component renders an unsorted table according to the data recieved from these 3 props. Two of them are for data and another for an unique-key generator function.

Diagram
TablePage Diagram
Data Loading
TablePage Diagram

The data prop

The data prop accepts an array of objects. Where each object is a row, and each element inside a object should be values for all the columns on that row.

Diagram
TablePage data prop data-loading

For example the object for the first row in the first diagram would be,

{
    name:'Orange',
    color:'Orange',
    count:5,
}

and the Sq Count can be dynamicly calculated in the config prop (We will discuss about it later). So, the data prop should recieve a array of such objects.

The config prop

The config prop also accepts an array of objects. But here each object is a configuration of each column. The properties of these objects are more selective and limited. The properties that the Table component recognises in a object inside config array are,

  • label
  • render
  • sortValue
  • header

Diagram
Table component config array diagram

label

label is the header of the column. This property should be a string, and will be rendered inside a <th> tag, like -

<th>{config.obj.label}</th>

render

render property should be a function. This property tells the Table component that which property from data's objects should be rendered in this column. The function accepts one argument row, (that is any single object from data) and should return the property that should be rendered in this column as row.property. Demonstration is given in the diagram above and in the example below.

{
    label: 'some heading',
    render: (row) => row.name,
    ...
}

sortValue

This property in config objects is optional. If the column contains data, that can be logically sorted (i.e numbers, strings) then this property should be pressent in that column's config object. This property accepts a function, which recieves w single objects from data and returns that property that should be sorted,when user clicks on the header.

{
    label: 'some heading',
    render: (row) => row.name,
    sortValue: (row) => row.name,
}

header

This property is also super optional. This property can be used in times when developers want to show the heading inside any other tag or in any other style. In other words, this property can be used to control the behaviour of the heading of the column. This property accepts a fucntion, where it recieves nothing, but returns a jsx tag. This tag is expected to contain a heading, because this tag would be rendered in the column's heading's place.

{
    label: 'some heading',
    render: (row) => row.name,
    sortValue: (row) => row.name,
    header: () => <h1 style={{color:'#505050'}}>some heading</h1>
}

The KeyFn prop

The KeyFn prop accepts a function, which recieves an argument, that is a object from either data or config and should return a unique value according to the object passed. This value is used as unique key in mapped elements.

Example

const keyFn = (obj) => {
        if (obj.name) {
            return obj.name;
        } else if (obj.label) {
            return obj.label;
        }else {
            return obj[1];
        }
    }

The SortableTable component

SortableTable is a component to render a table with sortable optionalities. This table is dynamic and controlled by a dataset, in a other file or in a backend server as like the Table component. The SortableTable component has exactly the same data loading as the Table component, which means it recieves 3 props as data, config and KeyFn. The SortableTable component renders an unsorted table at first, but if clicked on the column headers, it renders the rows in acsending order according to the values of that column, then in next click it sorts in descending order and then on another click back to unsorted order. If clicked on any other headers, the sort-order cycle breaks and restarts. The 2 of the props are for data and another for a key generator function. There is no need to put repeated informations here, read about the data-loading and the role of the props above in the Table components' details.

Full Changelog: v2...v3

Version 2 Angur 🍇

12 Jun 07:50
Compare
Choose a tag to compare

Angur 🍇 (Version 2)

The version 2 of the Adprava app has a new page ModalPage. ModalPage is a demonstration of a component Modal. Modal is basically a popup box component. The Modal popup box has a bold centered title, a text for giving some message to the user and two buttons, one for conformation, called Proceed and another for cancelation, called Cancel. As we go along this Note, we will explore more technical details about it.

Modal Component

The component Modal

Modal is basically a popup box component that can be invoked from any other component and can be used for asking for any conformation from the user. This component sends back boolean message to it's parent component according to whether the user accepted the proposal or not.

Props

The Modal component accepts 4 props,

  • heading
  • message
  • closeModal
  • modalConformation

heading

The prop heading accepts a string that is supposed to be a short title of the Modal PopUp box.

message

The prop message also accepts a string that is rendered below the title in a normal font style and size like a paragraph. This prop is supposed to be used for passing the main textual content of the modal.

closeModal

The prop closeModal accepts a function, that should close the appearance of the Modal component in the parent component. This function should be passed to the Modal component with this prop. Whenever user clicks on any of the buttons or outside the modal in the background this function is invoked.

modalConformation

The modalConformation prop sends back a boolean parameter. The modalConformation prop should be given a handler function, that would have a conditional. If the user clicks on the Proceed Button, the modalConformation(true) function is invoked. And if the user clicks on the Cancel Button, the modalConformation(false) function is invoked. The parent component can take these boolean values and do some processing with a handler function.

The Page ModalPage

The ModalPage is just a demonstration of the Modal component. This page has a heading like all the other pages. This page has a Button component that invokes a function, which makes a boolean state modalsts true in the page. When this state is changed, a useEffect function invokes, which sets the Modal component's styles to be visible. This page also contains a handler function for the closeModal prop accepted by Modal component as handleCloseModal(). This function basically just makes the modalsts state false. Then this page also has the handler function for modalConformation prop accepted by Modal component as handleModalConformation(status). This function just just updates a state modalConf with the boolean value it gets from Modal. After this there is a useEffect function that invokes when the modalConf state changes and does some job according to the message it gets from the Modal.

Full Changelog: v1.2...v2

Version 1.2

10 Jun 10:28
Compare
Choose a tag to compare

Replaced the ButtonPage's diagram, as it was a mistakenly put a entire screenshot.

Full Changelog: v1.1...v1.2

Version 1.1

10 Jun 10:22
Compare
Choose a tag to compare

Changed names in couple of places, ButtonPage is now ButtonsPage and it's url is /Buttons, not /Button. This clearly makes more sense.

Full Changelog: v1...v1.1

Version 1 Narkel 🥥

09 Jun 15:06
Compare
Choose a tag to compare

The Version 1 Narkel contains Three Pages, namely Dropdown, Accordion and Button. Descriptions are given about these pages in the README.md in the root directory.

Accordion v1

31 May 15:23
Compare
Choose a tag to compare

Version one of the accordion component. In this version multiple accordion items can be expanded together, which will be changed in the future versions.