Showing posts with label React. Show all posts
Showing posts with label React. Show all posts

Saturday, July 31, 2021

Wait for State Changes with Redux Saga

Hello,

As we know Redux saga allows us to respond to actions outside Redux store. It's kind of middleware library to handle side effects with ease. This side effect could be anything like calling APIs, doing some IO operations or anything. While working with Saga sometime it happens that we also want to detect state changes and do some actions after it. In this blog I am going to explain how you can wait or detect Redux state changes with Saga.

Let's understand with an example. For example there is an API call to get access token and as soon as you have access toke available in state you want to call some other actions like background sync etc. 


function* waitForLoginToken(selector) {

    if (yield select(selector)) return;

    while (true) {

      yield take('*');

      if (yield select(selector)) return;

    }

}

export function* postSignInAction(payload) {

    cost loginTokenSelector = state => state.auth.loginToken;

    yield call(waitForLoginToken, loginTokenSelector);

    yield put({ type: 'BACKGROUND_SYNC' });

}

function* mySaga(){

  yield takeEvery('SIGN_IN', postSignInAction);

}

As you can see in above code, we take every sign in action and call postSignInAction which will wait for state change.

We defined state selector as state.auth.loginToken. Till the time loginToken is not set in state.auth it will wait as we are using while loop to wait for state change. Once we get it in state we call next action. 

This way you can & detect state change with Redux Saga. Hope this helps you.

Saturday, July 17, 2021

React-Draft-Wysiwyg - Find Text Option

Hello,

Recently I was working on POC for rich text editor using React-Draft-Wysiwyg editor. 

There we have a requirement to add find & replace dialog box which should find the matching text from all the blocks and height it with background color. For the POC we added find text functionality. Here in this blog I will explain how to do it. 

For this I have created separate React component and add it as custom option to editor toolbar. Let's understand it step by step. 

If you want to know how to add custom option you can find reference from here.

https://jpuri.github.io/react-draft-wysiwyg/#/docs

1) Create Modal with Text input and Button

Please note I have used grommet UI library to build the POC. So text input and button was imported from Grommet.

<TextInput

    data-cy="find-text"

    autoFocus

    onChange={this.onChangeFindText}

    value={this.state.findText}

/>

<Button

    id="find"

    label="Find"

    onClick={this.onFindClick}

/>

2) Handle Find Click Event

onFindClick = () => {

  const search = this.state.findText;

  let contentState = convertToRaw(this.props.editorState.getCurrentContent());

  contentState.blocks.forEach(block => {

    const text = block.text;

    const matches = [...text.matchAll(search)];

    if(matches.length > 0) {

      matches.forEach(match =>{

        block.inlineStyleRanges.push({length: match[0].length,

          offset: match.index,

          style: "bgcolor-rgb(247,218,100)"

        })

      });

    }

  });

  let newEditorState = {

    editorState: EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})),

    contentState: null

  }

  this.props.onChange(EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})));

}

In above code we are getting search text from the state and matching it with texts of all custom blocks. Where ever it matches we are setting inline styles in blocks with yellow color background. and then setting state of editor again with new blocks. 

Hope this helps you.

Saturday, June 26, 2021

How to Create Custom Theme for UI using Grommet V2

 Hello,

In this blog we will understand how you can create custom theme for your using Grommet V2 in your React app.

Using Grommet v2, you can leverage the theme capabilities and define a customTheme as a JS object with your desired colors, margin padding etc. Let's see how we can do this. 

First define your custom theme as JS object. As you can see we have defined some existing grommet color like background, brand. Also we have defined our own color like custom-1, custom-2 etc and then used it in button. 

const customTheme = {

  global: {

    colors: {

      background: "#fff",

      brand: "#000",

      "custom-1": "#aaaaaa",

      "custom-2": "#bbbbbb",

      "custom-3": "#444444"

    }

  },

  button: {

    default: {

      background: "brand",

      color: "white"

    },

    primary: {

      background: "custom-1",

      color: "white"

    },

    secondary: {

      background: "custom-3",

      color: "dark-2"

    }

  }

}

For more information on theme customisation and JSON structure you can visit Official Grommet site

Now you can apply this theme to your application as below.

import { Grommet, Box } from 'grommet';

const DemoGrommet = () => (

  <Grommet theme={customTheme}>

     <Box background="custom-1" >

     </Box>

  </Grommet>

);

export default DemoGrommet;

In case you want to keep default values of Grommet theme and want to override only few things with your theme, you can use deepMerge function provided by grommet v2 utils. 

import { deepMerge } from 'grommet/utils';

import { generate } from 'grommet/themes/base';

const mergedTheme = deepMerge(generate(16), customTheme);

Here generate function generates default theme with 16 pixel font size and then it merge it with your custom theme and provide you updated theme.

Tuesday, August 20, 2019

ReactJs Material UI Table Infinite Scroll

Hello,

Recently in one of my ReactJs project, I faced a challenge in implementing infinite scroll in Material UI table. In this blog I am going to mention trick I have used.

First of all I was really surprised to see that Material UI table does not have infinite scroll function out of the box. It's very much needed. Sometimes something can not be achieved with frameworks, can be achieved via basics of JavaScript. In this I have done something similar.

I tried adding on scroll events on Table, Table Body but it didn't work. I also tried adding refs to body and then bind the Scroll event but that also did not work. After struggling for couple of hours, I finally decided to it with Pure JavaScript.

Step 1 : Wrap material UI table inside the container with fixed height and set overflow = scroll to container.


import styled from "styled-components";

export const Table = props => (
  <TableWrapper id={props.id}>
    <MuiTable {...props}/>
  </TableWrapper>

);

const TableWrapper = styled.div`
  max-height: 500px;
  overflow: scroll;

  ::-webkit-scrollbar {
    width: 3px;
    height: 3px;
  }
`;

As you can see I created a wrapper of table and set max height to it. You can make it dynamic as well depending on window height.

Step 2: Import Table to your component

import {
  Table

 } from './components/Table';

return (
          <>         
             <Table id={"tableID"}/>
          </>
        );

Step 3: Bind scroll event to wrapper

let me = this;
document.getElementById('tableID').onscroll = function(event){
   if(this.scrollTop == (this.scrollHeight - this.clientHeight)){
         //User reached bottom of table after scroll
         //Logic to call web services to get next set of data
   }
};

Hope this helps you.

Thursday, August 15, 2019

ReactJs / Angular - Override Material UI Theme

Hello,

While working with React or Angular Applications we normally uses Material UI themes and components and it's great choice because it has nice set of themes and colors and ready to use components. That makes our life easy.

One challenge we face is, in case if we want to change or override the theme. For example Material ui has dark blue theme. What if you want to change colors or dark blue theme with your own color. One option is you can declare the class with same name and give your own property. However the better solution is to use theme override. In this blog I am going to mention how to this.

Please note the method I am going to mention here is specific to React application.

First of all create theme.js file in your app and add following code to it.

import React from "react";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import blueGrey from "@material-ui/core/colors/blueGrey";
import lightBlue from "@material-ui/core/colors/lightBlue";
import "typeface-roboto";

import { ThemeProvider as ScThemeProvider } from "styled-components";

export default props => (
  <ScThemeProvider theme={muiTheme}>
    <MuiThemeProvider theme={muiTheme}>
      <CssBaseline>{props.children}</CssBaseline>
    </MuiThemeProvider>
  </ScThemeProvider>
);

const theme = {
  overrides: {
  },
  palette: {
    primary: { 
      main: '#MAIN_COLOR' 
    }, 
    secondary: { 
      main: '#SECONDARY_COLOR' 
    },
    background: {
      default: '#BACKGROUND_COLOR'
    }
  },
  type: "dark"
};

const muiTheme = createMuiTheme(theme);

Now here in overrides you can add code to override. For example if you want to change panel header. If you inspect html element you will find it has a class MuiPaper-root

Here is how you can override base CSS of it.

   overrides: {
    MuiPaper: {
      root: {
        background: '#YOUR_COLOR'
      },
      rounded: {
        background: '#YOUR_COLOR'
      }
    }

Same way for any other components you can do it. Inspect the HTML structure, find out Class Name and override it.

Tuesday, August 13, 2019

ReactJs - Convert JSON Data using loadash

Hello,

Finally now I am going to post few blogs on React and ReactJs. In this blog we are going to learn how we can modify, manipulate or edit JSON data received from API according to your need.

This will be very useful when your backend developer refused to change API response. So not to worry, let it be as it is and convert data on your side before you use it.

For this we are going to use Lodash library, so first of all add it your ReactJs project using npm and import it in your class file.

import _ from "lodash";

Now create function for converting data.

const convertData = (data, key) =>{
  let result = _.chain(data)
    .get(key)
    .map(d => ({
      modified_key1: _.get(d, "original_key1"),
      modified_key2: _.get(d, "original_key2"),
      modified_key3: _.get(d, "original_key3"),
      modified_key4: _.get(d, "original_key4")
    }))
    .value();
    return result;
}

Now call this function in your API response.

let modifiedData = convertData(response.body, "data");

Here data is the root key of your JSON response. Change it according to your JSON response. That's it now you have modified data according to your requirements.

Saturday, May 20, 2017

React Native undefined is not an object (evaluating 'this.props.navigator.push)

Hello,

Recently we have been working with React Native for one of our application where we faced an issue with Android Navigator. Basically we had two lists Category List and Sub Category List and on tap of category list item we wanted to render sub category list. Following is the code for that.

<TouchableOpacity onPress={()=> this.pressRow(rowData)} >
<CardSection>
 <View style={thumbnailContainerStyle}>
<Image
 style={thumbnailStyle}
 source={{ uri: rowData.image }}
/>
 </View>
 <View style={headerContentStyle}>
<Text style={headerTextStyle}>{rowData.name}</Text>
 </View>
</CardSection>
</TouchableOpacity>

And following is function where we were using navigator.push to go to next view.

pressRow (rowData) {

    if(rowData.subcategory == true)
    {
      this.props.navigator.push({
        name: SubCategoryList,
        passProps: {rowId:rowData.id}
      });
    }
    else if(rowData.subcategory == false)
    {
      this.props.navigator.push({
        name: ProductList,
        passProps: {rowId:rowData.id}
      });
    }

 }

Here we are getting problem with error, this.props.navigator is undefined so were not able to go to second screen.

The problem here is on scope as we were having category list rendered in app container like this.


<CategoryList />

So props of parent are not passed to child and hence navigator was not available. To solve this all you have to do it add your child component like this.

<CategoryList  navigator={this.props.navigator} />

And now navigator object will be available. Hope this solves your problem.


Saturday, April 29, 2017

Step By Step Guide to Install React Native and Create Mobile App in OSX

Hello,

Recently in projects we decided to use React Native to create cross platform mobile application. I faced some difficulties in installing ReactNative so here in this blog I will explain getting started with React Native and create cross platform mobile application.

1) Install Xcode and Xcode command lines tools.



Get Xcode from Mac App Store. Click Here

2) Install Xcode Command Line Tools, Open terminal and run following command.

xcode-select --install

3) Install Homebrew, Homebrew is a package manager to install missing package on OSX. Open terminal and run following command.

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

4) Install NodeJs and NPM. React comes package in NPM so we have to install it. Run following command in terminal

brew install node

After installation check with following command to see if it's installed.

node -v

npm -v

5) Install watchman with home brew.

brew install watchman

6) Install The React Native CLI

Node.js comes with npm, which lets you install the React Native command line interface.

Run the following command in a Terminal

npm install -g react-native-cli

7) Create React Native Project, run following commands in terminal.

react-native init ReactNativeTest

cd ReactNativeTest

Now run it with following command.

react-native run-ios

It will run application in iOS simulator.


react-native run-ios is just one way to run your app. You can also run it directly from within Xcode.



Step By Step Guide to Install and Create ReactJs Application in OSX

Hello,

Recently we have decided to use ReactJs for building mobile web applications and I faced some difficulties in setting up ReactJs in OSX so here in this blog I will explain step by step procedure from installation of ReactJS to creating and running application and Getting started with ReacJs in OSX

1) Install Xcode and Xcode command lines tools.



Get Xcode from Mac App Store. Click Here

2) Install Xcode Command Line Tools, Open terminal and run following command.

xcode-select --install

3) Install Homebrew, Homebrew is a package manager to install missing package on OSX. Open terminal and run following command.

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

4) Install NodeJs and NPM. React comes package in NPM so we have to install it. Run following command in terminal

brew install node

After installation check with following command to see if it's installed.

node -v

npm -v

5) Next we will install React, run following command in terminal.

npm install react

6) Now we will install Command line utility to create react app. Run following command in terminal.

npm install -g create-react-app

7) Create new react app. Run following commands in terminal.

create-react-app ReactApp
cd ReactApp
npm start

It should display following message in terminal.



And it will open ReactApp in your default browser.




That's it, Now you can work on ReactApp code and just refresh it in browser to see effect. Hope this helps you.