Plash: Build and Run Layered Root Filesystems

Plash

Build and run layered root filesystems.

Install / Uninstall

sudo sh -c "curl -Lf https://raw.githubusercontent.com/ihucos/plash/master/setup.sh | sh"

# uninstall
sudo rm -rf /usr/local/bin/plash /usr/local/bin/plash-exec /opt/plash/

Requirements

  • python3, bash, make and cc
  • Linux Kernel >= 4.18
  • unionfs-fuse, fuse-overlayfs or access to the kernel's builtin overlay filesystem
  • Optional newuidmap and newgidmap for setuid/setgid support with non-root users

Documentation

plash --from alpine --apk xeyes -- xeyes

https://ihucos.github.io/plash-docs-deploy/

Caveats

Plash processes have the same operating system access rights than the process that started it. There is no security relevant isolation feature. Exactly as with running programs "normally", don't run programs you do not trust with plash and try to avoid using plash with the root user.

Plash only runs inside Docker containers started with the --privileged flag, see GitHub issue #51 for details.

Nested plash instances are not possible with unionfs-fuse (#69). But fuse-overlayfs and overlay work fine.

Development Guidelines

  • Keep the script character.
  • Don't fall in love with the code, embrace its absence.
  • All dependencies will get unmaintained at some point.
  • Use honest thin wrappers, documented leaky abstractions are better then difficult promises.
  • Don't be a monolith but don't try too hard not to be one.
  • Don't complain or warn via stderr, do it or don't do it.
  • Only be as smart as necessary and keep it simple and stupid (KISS).
  • Still be able to run this in five years without any maintenance work.
  • No baggage, no worries.
  • Define well what this project is and especially what it is not.
  • Say no to features, say yes to solved use cases.
  • Postpone compromises.
  • Ditch everything that turns out too fiddly.
  • Be as vanilla as you can be
  • Be humble, don't oversell your abstraction layer.
  • Sometimes the dirty solution is cleaner than the proper one.
  • Don't differentiate root from non-root users (this is a TODO)
  • Crude is better than complex.
  • Only eat your own dog food if you are hungry.
  • Work towards a timeless, finished product that will require no maintenance.
  • Don't write C just because it looks cool, use the right tool for the right job.
  • The right guidelines for the right situation.

User Interface Guidelines

  • Interface follows code
  • Code supplements documentation
  • Documentation compensates a raw user interface
  • Put effort into documentation
  • If you want fun, go play outside
  • Focus on expert users and automated systems as CLI consumers
  • Don't make difficult things seem easy
  • Don't be too verbose, usually only information about success or failure matter
  • plash will be learned once but used multiple times
  • Avoid too many features slowly getting in
  • The UI is not a marketing instrument
  • Ugly wards testify emphasis on backward compatibility
  • Learning plash should be a valuable skill that lasts
  • Users don't know what they want
  • user errors are the user's fault
  • Rude is better than sorry
  • Technical descriptions do not get outdated, reasoning and interpretations do.

FAQ

Can I contribute?

Please! Write me an mail mail@irae.me, open an issue, do a pull request or ask me out for a friendly chat about plash in Berlin.

Who are you?

A Django/Python software-developer. Since this is an open source project I hope this software grows organically and collaboratively.

Why write a containerization software?

Technical idealism. I wanted a better technical solution for a problem. In my personal opinion Docker is revolutionary but has some shortcomings: awkward interface, reinvention of established software or interfaces, bundling, vendor lock in and overengineering. In a way it kills it's idea by trying too hard to build a huge company on top of it. Plash thrives not to be more than a useful tool with one task: Building and running containerized processes. Ultimately I wanted something I can if necessary maintain by myself.

Are there plans to commercialise this?

No, there isn't. At the same time I don't want to risk disappointing anyone and am not making any absolute guarantees.

What is the Licence?

plash is licensed under the MIT Licence.

How does the code look?

Some python3, some C. Very little code, very maintainable.

How does plash compare to Docker?

Docker is a bloated SUV you have to bring to the car workshop every week, for random alterations, features and new advertising stickers. Plash is a nice fixed gear bike, but the welds are still hot and nobody checked the bolts yet.

Can I run this in production?

You can. It probably still has some warts, what I can guarantee is to enthusiastically support this software and all issues that may come with it and focus on backward compatibility.

Is plash secure?

Plash does not use any daemons or have its own setuid helper binaries. Note that plash does not try to isolate containers (which are just normal processes). That means that running a program inside plash is not a security feature. Running any container software introduces more entities to trust, that is the root file system image with its additional linux distribution and its own package manager. Using a program from alpine edge could be considered less secure than a package from debian stable or vice versa. Also note that keeping containers updated is more difficult than keeping "normal" system software updated. Furthermore note that programs could be not used to run inside semi-isolated containers and behave oddly. Plash uses unmodified lxc images. Using plash as root should be avoided and should not be necessary for most use cases. Until now plash was written by one person and of course I could be wrong about something. But generally speaking it really should be good enough.


Download Details:

Author: ihucos
Source code: https://github.com/ihucos/plash/

License: MIT license

#linux 

What is GEEK

Buddha Community

Plash: Build and Run Layered Root Filesystems

The Best Way to Build a Chatbot in 2021

A useful tool several businesses implement for answering questions that potential customers may have is a chatbot. Many programming languages give web designers several ways on how to make a chatbot for their websites. They are capable of answering basic questions for visitors and offer innovation for businesses.

With the help of programming languages, it is possible to create a chatbot from the ground up to satisfy someone’s needs.

Plan Out the Chatbot’s Purpose

Before building a chatbot, it is ideal for web designers to determine how it will function on a website. Several chatbot duties center around fulfilling customers’ needs and questions or compiling and optimizing data via transactions.

Some benefits of implementing chatbots include:

  • Generating leads for marketing products and services
  • Improve work capacity when employees cannot answer questions or during non-business hours
  • Reducing errors while providing accurate information to customers or visitors
  • Meeting customer demands through instant communication
  • Alerting customers about their online transactions

Some programmers may choose to design a chatbox to function through predefined answers based on the questions customers may input or function by adapting and learning via human input.

#chatbots #latest news #the best way to build a chatbot in 2021 #build #build a chatbot #best way to build a chatbot

Riyad Amin

Riyad Amin

1571046022

Build Your Own Cryptocurrency Blockchain in Python

Cryptocurrency is a decentralized digital currency that uses encryption techniques to regulate the generation of currency units and to verify the transfer of funds. Anonymity, decentralization, and security are among its main features. Cryptocurrency is not regulated or tracked by any centralized authority, government, or bank.

Blockchain, a decentralized peer-to-peer (P2P) network, which is comprised of data blocks, is an integral part of cryptocurrency. These blocks chronologically store information about transactions and adhere to a protocol for inter-node communication and validating new blocks. The data recorded in blocks cannot be altered without the alteration of all subsequent blocks.

In this article, we are going to explain how you can create a simple blockchain using the Python programming language.

Here is the basic blueprint of the Python class we’ll use for creating the blockchain:

class Block(object):
    def __init__():
        pass
    #initial structure of the block class 
    def compute_hash():
        pass
    #producing the cryptographic hash of each block 
  class BlockChain(object):
    def __init__(self):
    #building the chain
    def build_genesis(self):
        pass
    #creating the initial block
    def build_block(self, proof_number, previous_hash):
        pass
    #builds new block and adds to the chain
   @staticmethod
    def confirm_validity(block, previous_block):
        pass
    #checks whether the blockchain is valid
    def get_data(self, sender, receiver, amount):
        pass
    # declares data of transactions
    @staticmethod
    def proof_of_work(last_proof):
        pass
    #adds to the security of the blockchain
    @property
    def latest_block(self):
        pass
    #returns the last block in the chain

Now, let’s explain how the blockchain class works.

Initial Structure of the Block Class

Here is the code for our initial block class:

import hashlib
import time
class Block(object):
    def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
        self.index = index
        self.proof_number = proof_number
        self.previous_hash = previous_hash
        self.data = data
        self.timestamp = timestamp or time.time()
    @property
    def compute_hash(self):
        string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
        return hashlib.sha256(string_block.encode()).hexdigest()

As you can see above, the class constructor or initiation method ( init()) above takes the following parameters:

self — just like any other Python class, this parameter is used to refer to the class itself. Any variable associated with the class can be accessed using it.

index — it’s used to track the position of a block within the blockchain.

previous_hash — it used to reference the hash of the previous block within the blockchain.

data—it gives details of the transactions done, for example, the amount bought.

timestamp—it inserts a timestamp for all the transactions performed.

The second method in the class, compute_hash , is used to produce the cryptographic hash of each block based on the above values.

As you can see, we imported the SHA-256 algorithm into the cryptocurrency blockchain project to help in getting the hashes of the blocks.

Once the values have been placed inside the hashing module, the algorithm will return a 256-bit string denoting the contents of the block.

So, this is what gives the blockchain immutability. Since each block will be represented by a hash, which will be computed from the hash of the previous block, corrupting any block in the chain will make the other blocks have invalid hashes, resulting in breakage of the whole blockchain network.

Building the Chain

The whole concept of a blockchain is based on the fact that the blocks are “chained” to each other. Now, we’ll create a blockchain class that will play the critical role of managing the entire chain.

It will keep the transactions data and include other helper methods for completing various roles, such as adding new blocks.

Let’s talk about the helper methods.

Adding the Constructor Method

Here is the code:

class BlockChain(object):
    def __init__(self):
        self.chain = []
        self.current_data = []
        self.nodes = set()
        self.build_genesis()

The init() constructor method is what instantiates the blockchain.

Here are the roles of its attributes:

self.chain — this variable stores all the blocks.

self.current_data — this variable stores information about the transactions in the block.

self.build_genesis() — this method is used to create the initial block in the chain.

Building the Genesis Block

The build_genesis() method is used for creating the initial block in the chain, that is, a block without any predecessors. The genesis block is what represents the beginning of the blockchain.

To create it, we’ll call the build_block() method and give it some default values. The parameters proof_number and previous_hash are both given a value of zero, though you can give them any value you desire.

Here is the code:

def build_genesis(self):
        self.build_block(proof_number=0, previous_hash=0)
 def build_block(self, proof_number, previous_hash):
        block = Block(
            index=len(self.chain),
            proof_number=proof_number,
            previous_hash=previous_hash,
            data=self.current_data
        )
        self.current_data = []  
        self.chain.append(block)
        return block

Confirming Validity of the Blockchain

The confirm_validity method is critical in examining the integrity of the blockchain and making sure inconsistencies are lacking.

As explained earlier, hashes are pivotal for realizing the security of the cryptocurrency blockchain, because any slight alteration in an object will result in the creation of an entirely different hash.

Thus, the confirm_validity method utilizes a series of if statements to assess whether the hash of each block has been compromised.

Furthermore, it also compares the hash values of every two successive blocks to identify any anomalies. If the chain is working properly, it returns true; otherwise, it returns false.

Here is the code:

def confirm_validity(block, previous_block):
        if previous_block.index + 1 != block.index:
            return False
        elif previous_block.compute_hash != block.previous_hash:
            return False
        elif block.timestamp <= previous_block.timestamp:
            return False
        return True

Declaring Data of Transactions

The get_data method is important in declaring the data of transactions on a block. This method takes three parameters (sender’s information, receiver’s information, and amount) and adds the transaction data to the self.current_data list.

Here is the code:

def get_data(self, sender, receiver, amount):
        self.current_data.append({
            'sender': sender,
            'receiver': receiver,
            'amount': amount
        })
        return True

Effecting the Proof of Work

In blockchain technology, Proof of Work (PoW) refers to the complexity involved in mining or generating new blocks on the blockchain.

For example, the PoW can be implemented by identifying a number that solves a problem whenever a user completes some computing work. Anyone on the blockchain network should find the number complex to identify but easy to verify — this is the main concept of PoW.

This way, it discourages spamming and compromising the integrity of the network.

In this article, we’ll illustrate how to include a Proof of Work algorithm in a blockchain cryptocurrency project.

Finalizing With the Last Block

Finally, the latest_block() helper method is used for retrieving the last block on the network, which is actually the current block.

Here is the code:

def latest_block(self):
        return self.chain[-1]

Implementing Blockchain Mining

Now, this is the most exciting section!

Initially, the transactions are kept in a list of unverified transactions. Mining refers to the process of placing the unverified transactions in a block and solving the PoW problem. It can be referred to as the computing work involved in verifying the transactions.

If everything has been figured out correctly, a block is created or mined and joined together with the others in the blockchain. If users have successfully mined a block, they are often rewarded for using their computing resources to solve the PoW problem.

Here is the mining method in this simple cryptocurrency blockchain project:

def block_mining(self, details_miner):
            self.get_data(
            sender="0", #it implies that this node has created a new block
            receiver=details_miner,
            quantity=1, #creating a new block (or identifying the proof number) is awarded with 1
        )
        last_block = self.latest_block
        last_proof_number = last_block.proof_number
        proof_number = self.proof_of_work(last_proof_number)
        last_hash = last_block.compute_hash
        block = self.build_block(proof_number, last_hash)
        return vars(block)

Summary

Here is the whole code for our crypto blockchain class in Python:

import hashlib
import time
class Block(object):
    def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
        self.index = index
        self.proof_number = proof_number
        self.previous_hash = previous_hash
        self.data = data
        self.timestamp = timestamp or time.time()
    @property
    def compute_hash(self):
        string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
        return hashlib.sha256(string_block.encode()).hexdigest()
    def __repr__(self):
        return "{} - {} - {} - {} - {}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
class BlockChain(object):
    def __init__(self):
        self.chain = []
        self.current_data = []
        self.nodes = set()
        self.build_genesis()
    def build_genesis(self):
        self.build_block(proof_number=0, previous_hash=0)
    def build_block(self, proof_number, previous_hash):
        block = Block(
            index=len(self.chain),
            proof_number=proof_number,
            previous_hash=previous_hash,
            data=self.current_data
        )
        self.current_data = []  
        self.chain.append(block)
        return block
    @staticmethod
    def confirm_validity(block, previous_block):
        if previous_block.index + 1 != block.index:
            return False
        elif previous_block.compute_hash != block.previous_hash:
            return False
        elif block.timestamp <= previous_block.timestamp:
            return False
        return True
    def get_data(self, sender, receiver, amount):
        self.current_data.append({
            'sender': sender,
            'receiver': receiver,
            'amount': amount
        })
        return True        
    @staticmethod
    def proof_of_work(last_proof):
        pass
    @property
    def latest_block(self):
        return self.chain[-1]
    def chain_validity(self):
        pass        
    def block_mining(self, details_miner):       
        self.get_data(
            sender="0", #it implies that this node has created a new block
            receiver=details_miner,
            quantity=1, #creating a new block (or identifying the proof number) is awared with 1
        )
        last_block = self.latest_block
        last_proof_number = last_block.proof_number
        proof_number = self.proof_of_work(last_proof_number)
        last_hash = last_block.compute_hash
        block = self.build_block(proof_number, last_hash)
        return vars(block)  
    def create_node(self, address):
        self.nodes.add(address)
        return True
    @staticmethod
    def get_block_object(block_data):        
        return Block(
            block_data['index'],
            block_data['proof_number'],
            block_data['previous_hash'],
            block_data['data'],
            timestamp=block_data['timestamp']
        )
blockchain = BlockChain()
print("GET READY MINING ABOUT TO START")
print(blockchain.chain)
last_block = blockchain.latest_block
last_proof_number = last_block.proof_number
proof_number = blockchain.proof_of_work(last_proof_number)
blockchain.get_data(
    sender="0", #this means that this node has constructed another block
    receiver="LiveEdu.tv", 
    amount=1, #building a new block (or figuring out the proof number) is awarded with 1
)
last_hash = last_block.compute_hash
block = blockchain.build_block(proof_number, last_hash)
print("WOW, MINING HAS BEEN SUCCESSFUL!")
print(blockchain.chain)

Now, let’s try to run our code to see if we can generate some digital coins…

Wow, it worked!

Conclusion

That is it!

We hope that this article has assisted you to understand the underlying technology that powers cryptocurrencies such as Bitcoin and Ethereum.

We just illustrated the basic ideas for making your feet wet in the innovative blockchain technology. The project above can still be enhanced by incorporating other features to make it more useful and robust.

Learn More

Thanks for reading !

Do you have any comments or questions? Please share them below.

#python #cryptocurrency

Plash: Build and Run Layered Root Filesystems

Plash

Build and run layered root filesystems.

Install / Uninstall

sudo sh -c "curl -Lf https://raw.githubusercontent.com/ihucos/plash/master/setup.sh | sh"

# uninstall
sudo rm -rf /usr/local/bin/plash /usr/local/bin/plash-exec /opt/plash/

Requirements

  • python3, bash, make and cc
  • Linux Kernel >= 4.18
  • unionfs-fuse, fuse-overlayfs or access to the kernel's builtin overlay filesystem
  • Optional newuidmap and newgidmap for setuid/setgid support with non-root users

Documentation

plash --from alpine --apk xeyes -- xeyes

https://ihucos.github.io/plash-docs-deploy/

Caveats

Plash processes have the same operating system access rights than the process that started it. There is no security relevant isolation feature. Exactly as with running programs "normally", don't run programs you do not trust with plash and try to avoid using plash with the root user.

Plash only runs inside Docker containers started with the --privileged flag, see GitHub issue #51 for details.

Nested plash instances are not possible with unionfs-fuse (#69). But fuse-overlayfs and overlay work fine.

Development Guidelines

  • Keep the script character.
  • Don't fall in love with the code, embrace its absence.
  • All dependencies will get unmaintained at some point.
  • Use honest thin wrappers, documented leaky abstractions are better then difficult promises.
  • Don't be a monolith but don't try too hard not to be one.
  • Don't complain or warn via stderr, do it or don't do it.
  • Only be as smart as necessary and keep it simple and stupid (KISS).
  • Still be able to run this in five years without any maintenance work.
  • No baggage, no worries.
  • Define well what this project is and especially what it is not.
  • Say no to features, say yes to solved use cases.
  • Postpone compromises.
  • Ditch everything that turns out too fiddly.
  • Be as vanilla as you can be
  • Be humble, don't oversell your abstraction layer.
  • Sometimes the dirty solution is cleaner than the proper one.
  • Don't differentiate root from non-root users (this is a TODO)
  • Crude is better than complex.
  • Only eat your own dog food if you are hungry.
  • Work towards a timeless, finished product that will require no maintenance.
  • Don't write C just because it looks cool, use the right tool for the right job.
  • The right guidelines for the right situation.

User Interface Guidelines

  • Interface follows code
  • Code supplements documentation
  • Documentation compensates a raw user interface
  • Put effort into documentation
  • If you want fun, go play outside
  • Focus on expert users and automated systems as CLI consumers
  • Don't make difficult things seem easy
  • Don't be too verbose, usually only information about success or failure matter
  • plash will be learned once but used multiple times
  • Avoid too many features slowly getting in
  • The UI is not a marketing instrument
  • Ugly wards testify emphasis on backward compatibility
  • Learning plash should be a valuable skill that lasts
  • Users don't know what they want
  • user errors are the user's fault
  • Rude is better than sorry
  • Technical descriptions do not get outdated, reasoning and interpretations do.

FAQ

Can I contribute?

Please! Write me an mail mail@irae.me, open an issue, do a pull request or ask me out for a friendly chat about plash in Berlin.

Who are you?

A Django/Python software-developer. Since this is an open source project I hope this software grows organically and collaboratively.

Why write a containerization software?

Technical idealism. I wanted a better technical solution for a problem. In my personal opinion Docker is revolutionary but has some shortcomings: awkward interface, reinvention of established software or interfaces, bundling, vendor lock in and overengineering. In a way it kills it's idea by trying too hard to build a huge company on top of it. Plash thrives not to be more than a useful tool with one task: Building and running containerized processes. Ultimately I wanted something I can if necessary maintain by myself.

Are there plans to commercialise this?

No, there isn't. At the same time I don't want to risk disappointing anyone and am not making any absolute guarantees.

What is the Licence?

plash is licensed under the MIT Licence.

How does the code look?

Some python3, some C. Very little code, very maintainable.

How does plash compare to Docker?

Docker is a bloated SUV you have to bring to the car workshop every week, for random alterations, features and new advertising stickers. Plash is a nice fixed gear bike, but the welds are still hot and nobody checked the bolts yet.

Can I run this in production?

You can. It probably still has some warts, what I can guarantee is to enthusiastically support this software and all issues that may come with it and focus on backward compatibility.

Is plash secure?

Plash does not use any daemons or have its own setuid helper binaries. Note that plash does not try to isolate containers (which are just normal processes). That means that running a program inside plash is not a security feature. Running any container software introduces more entities to trust, that is the root file system image with its additional linux distribution and its own package manager. Using a program from alpine edge could be considered less secure than a package from debian stable or vice versa. Also note that keeping containers updated is more difficult than keeping "normal" system software updated. Furthermore note that programs could be not used to run inside semi-isolated containers and behave oddly. Plash uses unmodified lxc images. Using plash as root should be avoided and should not be necessary for most use cases. Until now plash was written by one person and of course I could be wrong about something. But generally speaking it really should be good enough.


Download Details:

Author: ihucos
Source code: https://github.com/ihucos/plash/

License: MIT license

#linux 

野村  陽一

野村 陽一

1638638400

ReactフックとTypeScriptを使用してTodoリストアプリを構築する

何かを学ぶための最良の方法は、行うことです。このチュートリアルは、ReactフックとTypeScriptを使用して独自のtodoリストアプリを構築する方法を学ぶのに役立ちます。この簡単なチュートリアルを試して、独自のToDoリストアプリを作成し、JavaScript、React、TypeScriptを改善してください。
 

コードは私のGitHubにあります

ブリーフィング

このチュートリアルの目標は、独自のToDoリストアプリを作成することです。アプリ全般について。このtodoリストアプリは非常にシンプルなインターフェースを備えており、todoの作成、チェックオフ、削除など、最も重要な機能に焦点を当てています。コードについて。ReactフックとReactフック、主にuseStateフックを使用します。

useRefフックも使用する場合があります。このToDoリストアプリは状態を管理するためにReactフックを利用するため、クラスコンポーネントを使用する必要はありません。したがって、このアプリは機能コンポーネントのみを使用してビルドします。ToDoリストアプリのスタイル設定に関しては、外部のCSSスタイルシートを使用します。

最後にもう1つ。まず、すべてのtodoアイテムには一意のIDがあります。これらのIDは、todoアイテムの作成時に生成されます。このIDを使用して、todoを完了としてマークするか、削除します。これを簡単にするために、グッドプラクティスに従い、インデックスの使用を避けながら、shortidパッケージを使用します。

プロジェクトの設定

まず最初に、ToDoリストアプリの基本的なアプリを作成しましょう。create-react-app使用すると、これを非常に高速に実行できます。あなたは、このパッケージを使用することができnpm init react-app react-hooks-todo-list-app-ts --typescriptnpx create-react-app react-hooks-todo-list-app-ts --typescriptまたはyarn create react-app react-hooks-todo-list-app-ts --typescript。TypeScriptを使用したくない場合--typescriptは、コマンドの最後にあるフラグを省略してください。

これらのコマンドは、ワークフローのセットアップとほとんどすべての必要な依存関係を備えた、ToDoリストアプリの開始テンプレートを作成します。手動でインストールする必要がある依存関係が1つありshortidます。それは、このパッケージのとタイプです。だから、使用npm i shortidしてnpm i -D @types/shortidyarn add shortid及びyarn add -D @types/shortidまたはpnpm i shortidpnpm i -D @types/shortid

アプリテンプレートに付属しているReactロゴなどのアセットがいくつかあります。あなたはそれを必要としないのであなたはそれを取り除くことができます。非常に単純なバージョンは、次のpackage.jsonようになります。

{
  "name": "react-todo-list-hooks-ts",
  "version": "1.0.0",
  "description": "Simple Todo list app built with React hooks and TypeScript.",
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "main": "src/index.tsx",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "dependencies": {
    "react": "16.11.0",
    "react-dom": "16.11.0",
    "shortid": "2.2.15"
  },
  "devDependencies": {
    "@types/react": "16.9.11",
    "@types/react-dom": "16.9.4",
    "@types/shortid": "^0.0.29",
    "react-scripts": "3.2.0",
    "typescript": "3.7.2"
  }
}

TypeScriptを使用する場合は、次のようにtsconfigなります。

{
    "include": [
        "./src/*"
    ],
    "compilerOptions": {
        "lib": [
            "dom",
            "es2015"
        ],
        "jsx": "react",
        "target": "es5",
        "allowJs": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true
    }
}

最後に、このToDoリストアプリプロジェクトの最終的な構造を以下に示します。このチュートリアルで作業するときにこれを使用して、自分の方向を決めることができます。これで、ToDoリストアプリの作業を開始する準備が整いました。

react-hooks-todo-list-app-ts/
├─node_modules
├─public
│ ├─favicon.ico
│ ├─index.html
│ ├─manifest.json
│ └─robots.txt
├─src
│ ├─components
│ │ ├─todo-form.tsx
│ │ ├─todo-item.tsx
│ │ └─todo-list.tsx
│ ├─styles
│ │ └─styles.css
│ ├─index.tsx
│ ├─interfaces.ts
│ └─react-app-env.d.ts
├─ package.json
└─ tsconfig.json

インターフェース

最初に行うことは、ToDoリストアプリのインターフェースを作成することです。それらを使用して、コンポーネントpropstodoオブジェクトの形状を定義したり、それらを入力したりします。TypeScriptの代わりに純粋なJavaScriptを使用することにした場合は、この手順をスキップできます。4つのインターフェースを作成する必要があります。

1つはtodo(todoオブジェクト)用、1つはtodoフォーム用、1つはtodoリスト用、もう1つはtodoアイテム用です。todoオブジェクトには、3つのプロパティを持つことになりますidtextisCompletedTodoForm小道具のアレイ含むtodoオブジェクト及びhandleTodoCreate方法を。TodoList小道具が含まれていますhandleTodoUpdatehandleTodoRemovehandleTodoCompleteおよびhandleTodoBlurメソッドとの配列todoオブジェクトを。

TodoItem小道具が含まれていますhandleTodoUpdatehandleTodoRemovehandleTodoCompletehandleTodoBlurおよび単一todoのオブジェクト。

// Todo interface
export interface TodoInterface {
  id: string;
  text: string;
  isCompleted: boolean;
}

// Todo form interface
export interface TodoFormInterface {
  todos: TodoInterface[];
  handleTodoCreate: (todo: TodoInterface) => void;
}

// Todo list interface
export interface TodoListInterface {
  handleTodoUpdate: (event: React.ChangeEvent<HTMLInputElement>, id: string) => void;
  handleTodoRemove: (id: string) => void;
  handleTodoComplete: (id: string) => void;
  handleTodoBlur: (event: React.ChangeEvent<HTMLInputElement>) => void;
  todos: TodoInterface[]
}

// Todo item interface
export interface TodoItemInterface {
  handleTodoUpdate: (event: React.ChangeEvent<HTMLInputElement>, id: string) => void;
  handleTodoRemove: (id: string) => void;
  handleTodoComplete: (id: string) => void;
  handleTodoBlur: (event: React.ChangeEvent<HTMLInputElement>) => void;
  todo: TodoInterface;
}

Todoアイテムコンポーネント

最初に作成するコンポーネントは、todoアイテムです。ToDoリストに新しいToDoを追加すると、このアイテムコンポーネントがそれを表します。このコンポーネントは、いくつかの要素で構成されます。まず、todoをチェックするためのdivwithspan要素があります。チェックされていないアイテムには、境界線のある透明な円にスタイル設定された空のスパンが含まれます。

チェックされたToDoアイテムにはspan、緑色の円の中にチェックマークの付いたHTMLエンティティが含まれます。ラッパーにdivonClick、todoをチェック/チェック解除するためのハンドラーがあります。次は。で別のものにdivなりinputます。このinput要素を使用して、todoのタイトルまたはテキストをレンダリングします。これは、input要素を使用してすべてのToDoアイテムを編集可能にする最も簡単な方法です。

を通過したオブジェクトvalueから、属性を介して行われるタイトルをtodo渡しますprops。これinputとは別に、これには2つのハンドラメソッドがあります。1つはforでonBlur、もう1つはforonChangeです。最後の要素も、div「x」エンティティ/アイコンが付いたものになります。この要素を使用して、todoアイテムを削除します。

これdivには1つのonClickハンドラーがあります。以前のすべてのデータ、およびハンドラーメソッドと同様に、これも完全な小道具に渡されます。

TypeScriptを使用する場合は、TodoItemInterfaceインターフェイスをインポートし、interfaces.tsそれを使用してpropsこのコンポーネントのタイプを入力します。この後、onChangeハンドラーをinput要素にReact.ChangeEvent<HTMLInputElement>アタッチしているため、要素にonChangeハンドラーを入力しinputます。

// Import dependencies
import * as React from 'react'

// Import interfaces
import { TodoItemInterface } from './../interfaces'

// TodoItem component
const TodoItem = (props: TodoItemInterface) => {
  return (
    <div className='todo-item'>
      <div onClick={() => props.handleTodoComplete(props.todo.id)}>
        {props.todo.isCompleted ? (
          <span className="todo-item-checked"></span>
        ) : (
          <span className="todo-item-unchecked" />
        )}
      </div>

      <div className="todo-item-input-wrapper">
        <input
          value={props.todo.text}
          onBlur={props.handleTodoBlur}
          onChange={(event: React.ChangeEvent<HTMLInputElement>) => props.handleTodoUpdate(event, props.todo.id)}
        />
      </div>

      <div className="item-remove" onClick={() => props.handleTodoRemove(props.todo.id)}>
        ⨯
      </div>
    </div>
  )
}

export default TodoItem

ToDoリストコンポーネント

ToDoリストは、作成する2番目のコンポーネントになります。このコンポーネントは非常にシンプルになります。このコンポーネントはTodoItem、作成したばかりの、およびtodoを介しpropsたオブジェクトの配列のハンドラーメソッドを受け入れます。コンポーネント自体にはdiv、ラッパー要素として1つ含まれます。

この中divにはリスト、1つのul要素があります。この要素内でmap()は、todoオブジェクトの配列を反復処理し、オブジェクトごとにli1つのTodoItemコンポーネントを持つ1つの要素を作成するために使用しtodoます。次に、ハンドラーメソッドとともに、個々のtodoオブジェクトをTodoItemコンポーネントに渡します。

活字体の場合、輸入に覚えTodoListInterfaceインタフェースと入力し、それを使用propsするTodoListコンポーネントを。

// Import dependencies
import * as React from 'react'

// Import TodoItem
import TodoItem from './todo-item'

// Import interfaces
import { TodoListInterface } from './../interfaces'

// TodoList component
const TodoList = (props: TodoListInterface) => {
  return (
    <div className="todo-list">
      <ul>
        {props.todos.map((todo) => (
          <li key={todo.id}>
            <TodoItem
              todo={todo}
              handleTodoUpdate={props.handleTodoUpdate}
              handleTodoRemove={props.handleTodoRemove}
              handleTodoComplete={props.handleTodoComplete}
              handleTodoBlur={props.handleTodoBlur}
            />
          </li>
        ))}
      </ul>
    </div>
  )
}

export default TodoList

Todoフォームコンポーネント

ToDoの「フォーム」は、useStateReactフックを使用する最初のコンポーネントです。useRefReactフックを使用する場所でもあります。新しいtodoアイテムを作成する前に、useStateフックを使用して、input要素に渡されたテキスト、todoタイトルのテキストを保存します。

useRefフックを使用して、この入力への参照を保存します。新しいToDoを作成する方法は、「Enter」キーを押しながら、その入力内にテキストを入力することです。したがって、「Enter」キーを押すと、値を空の文字列に設定することにより、この参照を使用して入力をリセットします。この入力には、との2つのハンドラメソッドもonChangeありonKeyPressます。

これら二つのハンドラメソッドは次のようになりますhandleInputChangehandleInputEnter。1つ目はonChange、入力に何かを書き込んだときにフォームの状態を更新します。いくつかのToDoタイトル/テキストです。2つ目は、の場合onKeyPress、新しいtodoオブジェクトを作成し、「Enter」キーの押下を検出すると入力フィールドをリセットします。

shortidパッケージを覚えていますか?ここで、この依存関係を使用します。内部handleInputEnter機能、新しい内部のtodoオブジェクト、あなたが使用するshortidユニーク生成するidすべての新しいTODOのために。心配しないでください。これは簡単です。必要なのは、呼び出すことですgenerate()shortidして、新しいはid準備ができています。

最後に、TypeScriptのいくつかのこと。まず、インポートTodoInterfaceTodoFormInterfaceインターフェース。次いで、使用TodoInterface新しい入力するインターフェースをtodoオブジェクト内をhandleInputEnter、そしてTodoFormInterface入力するためのインタフェースpropsTodoForm。次に、useRefを使用してフックを入力し<HTMLInputElement>、に設定しnullます。

その後、2つのイベントもあります。1つ目は、要素にハンドラーをReact.ChangeEvent<HTMLInputElement>アタッチしているため、で入力できます。2つ目は、キーの押下を「リッスン」しているため、で入力できます。onChangeinputReact.KeyboardEvent

// Import dependencies
import * as React from 'react'
import shortid from 'shortid'

// Import interfaces
import {TodoInterface, TodoFormInterface} from './../interfaces'

// Todo form component
const TodoForm = (props: TodoFormInterface) => {
  // Create ref for form input
  const inputRef = React.useRef<HTMLInputElement>(null)

  // Create form state
  const [formState, setFormState] = React.useState('')

  // Handle todo input change
  function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
    // Update form state with the text from input
    setFormState(event.target.value)
  }

  // Handle 'Enter' in todo input
  function handleInputEnter(event: React.KeyboardEvent) {
    // Check for 'Enter' key
    if (event.key === 'Enter') {
      // Prepare new todo object
      const newTodo: TodoInterface = {
        id: shortid.generate(),
        text: formState,
        isCompleted: false
      }

      // Create new todo item
      props.handleTodoCreate(newTodo)

      // Reset the input field
      if (inputRef && inputRef.current) {
        inputRef.current.value = ''
      }
    }
  }

  return (
    <div className="todo-form">
      <input
        ref={inputRef}
        type="text"
        placeholder='Enter new todo'
        onChange={event => handleInputChange(event)}
        onKeyPress={event => handleInputEnter(event)}
      />
    </div>
  )
}

export default TodoForm

メイン(インデックス)コンポーネント

ほぼ完了です。構築する必要のあるコンポーネントは1つだけです。これがTodoListApp主成分です。このコンポーネントは、ToDoを作成、更新、削除、および完了するためのメソッドを実装します。これは、を介して行われますhandleTodoCreatehandleTodoUpdatehandleTodoRemoveおよびhandleTodoComplete方法。

useStateReactフックを使用して、既存のすべてのToDoを保存するのもこのコンポーネントです。それでは、このコンポーネントを段階的に構築してみましょう。

輸入

まず、通常どおり、の依存関係をインポートする必要がありますreact。ここで、renderからメソッドをインポートする必要もありますreact-dom。これは、TodoListAppコンポーネントであるToDoリストアプリをDOMでレンダリングするためです。

またTodoFormTodoListコンポーネントをインポートして、後でそれらを返し、レンダリングできるようにします。これらのコンポーネントをインポートするときは、メインの外部CSSスタイルシートもインポートする必要があります。これにより、後でToDoリストアプリのスタイルを設定できます。

TypeScriptの場合、TodoInterfaceインターフェイスをインポートする必要があります。このインターフェースを数回使用して、todos状態といくつかのメソッドパラメーターを入力します。

// Import dependencies
import * as React from 'react'
import { render } from 'react-dom'

// Import components
import TodoForm from './components/todo-form'
import TodoList from './components/todo-list'

// Import interfaces
import { TodoInterface } from './interfaces'

// Import styles
import './styles/styles.css'

ToDoリストアプリの状態を作成する

ToDoリストアプリの状態はシンプルになります。オブジェクトの配列になります。1つのオブジェクトは1つの既存のToDoを表します。最初に、todos状態を空の配列として初期化します。

TypeScriptの場合は、必ずTodoInterfaceインターフェイスを[]。と一緒に使用してください。これにより、1つのtodoオブジェクトだけでなく、todosオブジェクトの配列について「話している」ことがTypeScriptに通知されます。

// TodoListApp component
// ....
const TodoListApp = () => {
  const [todos, setTodos] = React.useState<TodoInterface[]>([])
  // ...
}

新しいtodoの作成

ToDoリストアプリの最初のメソッドは、新しいToDoを作成するhandleTodoCreateメソッドメソッドです。このメソッドは、1つのパラメーターであるtodoオブジェクトを受け入れます。それが機能する方法は簡単です。まず、newTodosState現在のtodoリストアプリの状態をコピーして、新しいtodoリストアプリの状態を作成します。

次に、todoオブジェクトを取得し、このメソッドを呼び出すときにパラメーターとして渡し、それtodoを新しいtodoリストアプリの状態であるnewTodosState、usingpush()メソッドに追加します。その後、setTodos()メソッドを使用して、ToDoリストアプリの状態を更新します。

TypeScriptについて。TodoInterfaceインターフェイスを使用してtodoパラメータを入力します。また、このインターフェースを使用してnewTodosState変数を入力します。この場合、todoオブジェクトの配列が必要であることを再度指定し、の[]後に追加しTodoInterfaceます。

  // ....
  // Creating new todo item
  function handleTodoCreate(todo: TodoInterface) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Update new todos state
    newTodosState.push(todo)

    // Update todos state
    setTodos(newTodosState)
  }
  // ....

既存のToDoを更新する

次に、既存のタスクを更新するhandleTodoUpdateメソッド、メソッドが必要になります。この方法は、2つのパラメータを受け入れ、でしょうeventidid一意になりid、すべてのTODOアイテム/オブジェクトに対して生成さ。と同様にhandleTodoCreate、このメソッドもnewTodosState、現在のtodoリストアプリの状態をコピーして、新しいtodoリストアプリの状態を作成することから始まります。

次に、find()メソッドを使用してnewTodosState変数を反復処理し、id渡された引数を使用して、更新する正しいToDoアイテムを見つけます。正しいtodoアイテム/オブジェクトが見つかると、textキーの値が変更されます。Newvalueは、特定のtodoアイテム内の入力の値から取得されます。

最後のステップはnewTodosStatesetTodos()メソッドを使用して、ToDoリストアプリの状態を更新することです。

TypeScriptの場合、TodoInterfaceインターフェイスを使用して、メソッドにtodo渡されるパラメーターを入力しますfind()。の後newTodosStateと一緒に、変数にも使用します。最後に、パラメータをとして入力します。[]TodoInterfaceidstring

  // ....
  // Update existing todo item
  function handleTodoUpdate(event: React.ChangeEvent<HTMLInputElement>, id: string) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Find correct todo item to update
    newTodosState.find((todo: TodoInterface) => todo.id === id)!.text = event.target.value

    // Update todos state
    setTodos(newTodosState)
  }
  // ....

既存のToDoを削除する

ToDoの削除は、filter()メソッドを使用して実行されます。まず、newTodosState現在のToDoリストアプリの状態をコピーして、新しいToDoリストアプリの状態を作成します。この間、このfilter()メソッドを使用して、削除するToDoを削除します。これはid、すべてidのtodoを削除するtodoと比較することによって行われます。

これが完了すると、この新しいフィルタリングされたtodos状態を使用して、setTodos()メソッドで状態を更新します。

TypeScriptの場合、TodoInterfaceインターフェイスを使用して、メソッドにtodo渡されるパラメーターを入力しますfilter()。次に、。の後newTodosStateと一緒に、変数にも使用します。最後に、パラメータをとして入力します。[]TodoInterfaceidstring

  // ....
  // Remove existing todo item
  function handleTodoRemove(id: string) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = todos.filter((todo: TodoInterface) => todo.id !== id)

    // Update todos state
    setTodos(newTodosState)
  }
  // ....

ToDoの完了

ToDoを完了する方法は、方法と非常によく似ていhandleTodoUpdateます。まず、現在のToDoリストアプリの状態をコピーしてnewTodosState変数に保存します。次に、find()メソッドを使用して、todos状態内の特定のToDoアイテム/オブジェクトを検索します。

今回isCompletedは、特定のToDoアイテム/オブジェクトのキーの値を無効にします。この後、setTodosメソッドを使用してtodos状態を更新します。

さて、TypeScriptについて。まず、TodoInterfaceインターフェースを使用して、メソッドにtodo渡されるパラメーターを入力しますfind()。次に、このインターフェイスをnewTodosState変数にも使用します。これも。の[]後に付けTodoInterfaceます。最後のタイプはid。用になります。これはになりますstring

  // ....
  // Check existing todo item as completed
  function handleTodoComplete(id: string) {
    // Copy current todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Find the correct todo item and update its 'isCompleted' key
    newTodosState.find((todo: TodoInterface) => todo.id === id)!.isCompleted = !newTodosState.find((todo: TodoInterface) => todo.id === id)!.isCompleted

    // Update todos state
    setTodos(newTodosState)
  }
  // ....

すべてのtodoにタイトルがあることを確認する

最後のこと。既存のToDoを編集するときに、テキスト/タイトルを空のままにすると、警告が表示されるはずです。これを行うために、inputすべてのToDo内の要素の変更を見ることができます。その後、あなたはそのを確認することができvalue、空の文字列ではないlengthのは、value「0」よりも大きいです。

空の文字列がある場合は、特定のCSSクラスを追加します。テキストを入力すると、そのCSSクラスが削除されます。このCSSクラスは、入力を赤い境界線でマークします。このクラスは、後でCSSスタイルシートで定義します。

いつものように、TypeScript。これは迅速になります。入力する必要があるのeventは、パラメーターとして渡されることだけです。要素にonChangeイベントハンドラーをアタッチしているのでinput、を使用できますReact.ChangeEvent<HTMLInputElement>

  // ....
  // Check if todo item has title
  function handleTodoBlur(event: React.ChangeEvent<HTMLInputElement>) {
    if (event.target.value.length === 0) {
      event.target.classList.add('todo-input-error')
    } else {
      event.target.classList.remove('todo-input-error')
    }
  }
  // ....

すべてのコンポーネントを返す

ToDoリストアプリはほぼ完成しています。ここで、これまでに作成し、コンポーネントにインポートしたすべてのコンポーネントを取得して、それらを返す必要があります。すべてのコンポーネントに必要なものを必ず提供してくださいprops。その後、render()メソッドを使用TodoListAppしてDOMでレンダリングできます。

  // ...
  return (
    <div className="todo-list-app">
      {/* Todo form component */}
      <TodoForm
        todos={todos}
        handleTodoCreate={handleTodoCreate}
      />

      {/* Todo list component */}
      <TodoList
        todos={todos}
        handleTodoUpdate={handleTodoUpdate}
        handleTodoRemove={handleTodoRemove}
        handleTodoComplete={handleTodoComplete}
        handleTodoBlur={handleTodoBlur}
      />
    </div>
  )
}

// Render the App in the DOM
const rootElement = document.getElementById('root')
render(<TodoListApp />, rootElement)

すべてを一緒に入れて

あなたはこの主要なコンポーネントでたくさんのコードを書きました。より明確にするために、すべてをまとめましょう。

// Import dependencies
import * as React from 'react'
import { render } from 'react-dom'

// Import components
import TodoForm from './components/todo-form'
import TodoList from './components/todo-list'

// Import interfaces
import { TodoInterface } from './interfaces'

// Import styles
import './styles/styles.css'

// TodoListApp component
const TodoListApp = () => {
  const [todos, setTodos] = React.useState<TodoInterface[]>([])

  // Creating new todo item
  function handleTodoCreate(todo: TodoInterface) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Update new todos state
    newTodosState.push(todo)

    // Update todos state
    setTodos(newTodosState)
  }

  // Update existing todo item
  function handleTodoUpdate(event: React.ChangeEvent<HTMLInputElement>, id: string) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Find correct todo item to update
    newTodosState.find((todo: TodoInterface) => todo.id === id)!.text = event.target.value

    // Update todos state
    setTodos(newTodosState)
  }

  // Remove existing todo item
  function handleTodoRemove(id: string) {
    // Prepare new todos state
    const newTodosState: TodoInterface[] = todos.filter((todo: TodoInterface) => todo.id !== id)

    // Update todos state
    setTodos(newTodosState)
  }

  // Check existing todo item as completed
  function handleTodoComplete(id: string) {
    // Copy current todos state
    const newTodosState: TodoInterface[] = [...todos]

    // Find the correct todo item and update its 'isCompleted' key
    newTodosState.find((todo: TodoInterface) => todo.id === id)!.isCompleted = !newTodosState.find((todo: TodoInterface) => todo.id === id)!.isCompleted

    // Update todos state
    setTodos(newTodosState)
  }

  // Check if todo item has title
  function handleTodoBlur(event: React.ChangeEvent<HTMLInputElement>) {
    if (event.target.value.length === 0) {
      event.target.classList.add('todo-input-error')
    } else {
      event.target.classList.remove('todo-input-error')
    }
  }

  return (
    <div className="todo-list-app">
      <TodoForm
        todos={todos}
        handleTodoCreate={handleTodoCreate}
      />

      <TodoList
        todos={todos}
        handleTodoUpdate={handleTodoUpdate}
        handleTodoRemove={handleTodoRemove}
        handleTodoComplete={handleTodoComplete}
        handleTodoBlur={handleTodoBlur}
      />
    </div>
  )
}

const rootElement = document.getElementById('root')
render(<TodoListApp />, rootElement)

スタイル

ToDoリストアプリの準備が整いました。よくほとんど。いくつかのスタイリングのためのスペースがたくさんあります。ToDoリストアプリの見栄えを良くするために使用できるスタイルを次に示します。

/* Default styles*/
html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

#root,
body {
  min-height: 100vh;
}

body {
  margin: 0;
}

#root,
.todo-list-app {
  display: flex;
  flex-flow: column nowrap;
}

#root {
  align-items: center;
  width: 100%;
}

/* Todo list app styles  */
.todo-list-app {
  padding-top: 32px;
  width: 100%;
  max-width: 480px;
}

/* Todo form styles */
.todo-form input,
.todo-item {
  border: 1px solid #ececec;
}

.todo-form input {
  padding: 0 14px;
  width: 100%;
  height: 48px;
  transition: .25s border ease-in-out;
}

.todo-form input:focus {
  outline: 0;
  border: 1px solid #3498db;
}

/* Todo list styles */
.todo-list ul {
  padding: 0;
  margin: 0;
}

.todo-list li {
  list-style-type: none;
}

/* Todo item styles */
.todo-item {
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  padding: 8px;
}

.todo-form + .todo-list ul .todo-item {
  border-top: 0;
}

.todo-item-input-wrapper {
  flex-grow: 1;
  padding: 0 16px;
}

.todo-item input {
  width: 100%;
  border: 0;
  border-bottom: 1px solid transparent;
  transition: .25s border-bottom ease-in-out;
}

.todo-item input:focus {
  outline: 0;
  border-bottom: 1px solid #3498db;
}

.todo-item .todo-input-error {
  border-bottom: 1px solid #e74c3c;
}

.todo-item span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid #ececec;
  transition: .25s all ease-in-out;
}

.todo-item-unchecked:hover {
  background: hsla(168, 76%, 42%, .25);
  border: 1px solid hsl(168, 76%, 42%, .25);
}

.todo-item-checked {
  color: #fff;
  background: #1abc9c;
  border: 1px solid #1abc9c;
}

.item-remove {
  display: flex;
  padding-left: 8px;
  padding-right: 8px;
  font-size: 28px;
  cursor: pointer;
  line-height: 1;
  color: #ececec;
  transition: .25s color ease-in-out;
}

.item-remove:hover {
  color: #111;
}

結論:ReactフックとTypeScriptを使用してTodoリストアプリを構築する方法

おめでとうございます。ReactフックとTypeScriptを使用して、独自のToDoリストアプリを作成しました。ただし、ここで停止する必要はありません。だから、どうぞ。このtodoリストアプリを取り、それをより良くしてください。どのような機能が必要かを考えてください。その後、何も待たないでください。自分で実装してみてください。楽しむ!

この記事が気に入ったら、今後の投稿を見逃さないように購読してください。


リンク: https://blog.alexdevero.com/todo-list-app-react-hooks-typescript/

#typescript #react-native 

A Best Leading Matrimonial Website Development Company In India

Matrimonial Development

  1. Home
  2. Matrimonial Website Development

A Best Leading Matrimonial Website Development Company In India

Launching New Marriage Bureaus & Matrimonial Website With In 2 Days With Advanced Features For Grand Business Success Is Just A Call Away.

Matrimonial Website Design & Development Company In India

If you want to start a matrimonial business in India you need the best matrimonial website. It is one of the best and leading matrimonial website design, matrimonial website development companies in Coimbatore, Tamil Nadu, India. We make use of advanced technologies to make it an excellent experience for those seeking matchmaking services online. our matrimonial website provides a completely flexible and automated business solution to gain from this business opportunity in the fast-growing environment in India.

To Start Marriage Bureaus & Matrimonial Business Is Just A Call Away

We are the top best Matrimonial Portal Development Company, We are the best in the Market.

matrimonial web development

 

To Start Marriage Bureaus

UNLIMITED MEMBERS REGISTRATION

Two types of member types are available in our matrimonial website. free members & premium members. admin has full control over when new members registered on the website.

Online Payment Options

ONLINE PAYMENT OPTIONS

The payment gateway is integrated into the system so free members can pay money through an online transfer with debit cards, credit cards, net banking and became premium members and make use of advanced features in the matrimonial website.

Horoscope Profile Matching

HOROSCOPE PROFILE MATCHING

Members can generate horoscope birth charts and match the profile to get the result easily without astrologer help. with birth chart generator systems integrated into our matrimonial web application.

FUNCTIONALITY IS EXTREMELY IMPORTANT FOR MATRIMONY

Matrimonial Website With Unlimited Features

Software is a Coimbatore, India based matrimonial Web Development Company with a readymade matrimony website with the demo. If you are looking for the best matrimonial website development company in India. This is a very powerful online matrimony management software system that we’ve developed exclusively and user-friendly and should be the main features in the matrimonial portal.

MEMBERS

  • Two types of member options are available. Free Members & Premium Members. For Users

Free Members

#Root admin can get the list of all free member's information of each user. Admin can View the free member profiles, packages, followers, membership Information & also can block any Member any time he wishes.

Premium members

#Root admin can get the list of all premium members' information of registered members. admin can view the premium member profiles, packages, followers, membership duration, remaining premium package items & also can block any premium member any time.

Create Members By Admin

#Root Admin can create member profiles manually with all the basic information from his/her. Admin panel With Unique Profile ID for Every individual member registered by admin will get a unique member ID from the member Registration.

Member profile Attributes

Admin can Add, Edit Or Delete the following member attributes

  • Religion's
  • Caste
  • Sub-caste
  • Language
  • Family Status
  • Family Value
  • On Behalf
  • Country's
  • State's
  • City's

OUR MATRIMONY BUNDLED WITH ALL FUNCTIONALITY

To Start Online Matrimonial Website

  • Register / Login
  • Complete high-Security Website
  • Fully Customized and square admin panel
  • For all Regions and caste / sub-casts
  • Fully Custom Membership Plans
  • Mobile Responsive matrimonial website
  • Free Members Profile
  • Premium Members Profile
  • ecommerce Ready Website
  • Payments Invoices
  • Horoscope Systems
  • Fully customizable for your community
  • Admin can add/edit/delete/de-activate profiles.
  • Customer Support Ticketing System
  • Contact Messages
  • Online Payments Debit/Credit, Net banking
  • Email Setup
  • Sms Settings
  • Advanced Search Options
  • Search by Profile ID
  • Search-engine friendly Matrimonial Website
  • User-friendly Matrimonial Website
  • Family Info – Father, Mother name, status, etc.
  • Approve / Disapprove Members
  • Send private message to members
  • De-active OR BAN members any time

ELITE MATRIMONIAL WEBSITE FEATURES FOR A SUCCESSFUL BUSINESS

TOP & BEST MATRIMONY SOFTWARE COMPANY IN INDIA. 

USER FRIENDLY INTERFACE

Easy to navigate throughout the websites help brides and grooms use the websites easily find matches and communicate the profiles easily.

ADVANCED SEARCH OPTIONS

Advanced search options help brides and grooms to search the matching profile easily and find their perfect match profile for their life partner.

SEO-FRIENDLY WEBSITE

Our Matrimonial Websites are built for search engines in mind to bring more search visitors through search engines like google, bing, yahoo.

FULLY RESPONSIVE WEBSITE

Our Matrimony website is fully responsive it can be loaded faster in any device screen like mobile devices, tablets, and HD TV to Monitors. Our website will dynamically change to all devices.

MULTIPURPOSE MATRIMONY

A very powerful online matrimony management application system that we’ve developed exclusively and user-friendly. matchmaking, partner search, community-based wedding.

ON TIME DELIVERY

customized marriage bureaus & matrimonial Website for your business within 2 - 10 days no need to wait for a long time. we will deliver the matrimonial portal on time no delay.

AFFORDABLE PRICE

Matrimonial website designing is not a costly thing. You can build your own matchmaking matrimony website for an affordable price. We never compromise in quality.

FAST LOADING WEBSITE

When it comes to online speed is very important our Matrimonial website loads faster than any other matrimony website. Our speed score is 90 is based on the lab data analyzed.

ECOMMERCE READY WEBSITE

Our matrimony is the ecommerce Ready Website. so paid online like debit card, credit card, net banking, etc. free member can upgrade to Premium plan through an online payment.

We Develop Three Categories For Matrimonial Websites Development

We have three categories for matrimonial because every business owner wants different types of matrimony that's why we have three options for every matrimony business owner.

Basic Matrimonial

Basic Matrimonial

Only Basic Features Enabled

  • Basic Register / Login
  • Basic Admin Panel
  • Mobile Responsive Website
  • Contact Messages form Website
  • Search Options Enabled
  • Search by Profile ID Enabled
  • Email Setup
  • De-active OR BAN members
  • 1 year to support & updates

Premium Matrimonial

Premium Matrimonial

Premium Features Enabled

  • Premium Register / Login
  • Premium Admin Panel
  • Mobile Responsive Website
  • Free, Premium Members
  • ecommerce Ready Website
  • Advanced Search Options
  • Search-engine friendly
  • User-friendly Matrimonial
  • 2 year to support & updates

Enterprise Matrimonial

Enterprise Matrimonial

Elite Features Enabled

  • Ultimate Register / Login
  • Complete high-Security
  • ecommerce Ready Website
  • Payments Invoices
  • Horoscope Systems
  • Fully customizable Search-engine friendly
  • Advanced Search Options
  • OTP Login
  • 5 year to support & updates

MATRIMONAL MOBILE APP DEVELOPMENT COMPANIES IN COIMBATORE, INDIA

We provide end-to-end matrimonial mobile application design and development services in India. Incredible ideas require resources to get anything beyond the idea frame. That’s why we’ve built a process that can adapt to the needs of any client. want to work with a team that understands matrimonial service or business to build your app for success. you are in the right place to build your matrimonial app.

REQUEST A FREE CONSULTATION AND GET A NO OBLIGATION QUOTE FOR YOUR PROJECT WITHIN 8 BUSINESS HOURS

Lets build your next project Together!

WHAT ABOUT CUSTOMER SUPPORT & TECHNICAL SUPPORT?

We Have Dedicated Customer Service Support To Help

As a market leader in developing matrimonial website development in Coimbatore, India.  After developing matrimony completed. We aware Well Our customers need help from us like customer support and technical support frequently. So we provide an excellent and experienced team that will guide you and help you with your matrimonial website up and running without no issues.

We deliver high-quality premium customer support for matrimony service. We have a separate dedicated support developer team that will support all our clients. Our Support service is the developer team. So your issue and error will be solved within 15 Min we will take care of your website even at the weekend.

A 24/7 Premium Customer Team Will Be Delivered To All Our Clients For The Matrimonial Website.