I've got a NextJS 13 application which is using the Tailwind CSS framework to style the UI. The app is using the Boardgame Atlas API to fetch a board game for the user based on a few dropdown list items (category, player count, and spend).
The Home component is the main component of the app and is responsible for fetching the board game from the API and rendering the UI. It uses three other components, CategoriesSelect, PlayerCount, and SpendSelect to render the dropdown lists.
The CategoriesSelect component fetches the available categories from the API and renders a dropdown list to allow the user to select the category. The PlayerCount component renders a dropdown list to allow the user to select the minimum number of players needed for the game. The SpendSelect component renders a dropdown list to allow the user to select their budget.
Once the user selects the values from the dropdown lists, the fetchOutput function is called on the click of the "Find my game" button. This function makes a GET request to the API using the selected values, and the API returns the matching games. If there are any games found, the first game in the array is logged to the console, otherwise an error message is logged.
The code can be found on GitHub here, and a live version is available on Vercel here. I've also pasted the code below for convenience:
page.js (HOME)
"use client"
import { useState, useEffect } from 'react';
import CategoriesSelect from "#/components/CategoriesSelect";
import PlayerCount from "#/components/PlayerCount";
import SpendSelect from "#/components/SpendSelect";
import axios from 'axios';
export default function Home() {
const[formData, setFormData] = useState({
category: "",
playerCount: 1,
spend: 25,
})
const fetchOutput = async () => {
console.log(formData)
try {
const { data } = await axios.get(
`https://api.boardgameatlas.com/api/search?categories=${formData.category}&min_players=${formData.playerCount}<_price=${formData.spend}&client_id=EsdgqvppMg`
);
if (data.games && data.games.length > 0) {
console.log(data.games[0]);
} else {
console.error('No games found');
}
} catch (error) {
console.error(error);
}
};
// useEffect(() => {
// console.log(formData)
// }, [formData])
return (
<main >
<div className="text-center mt-24 mb-16 text-4xl font-mono">looking for your next boardgame?</div>
<div className="text-center font-mono px-10 mb-4">
<span>I want to play a(n) </span>
<CategoriesSelect
formData={formData.category}
setFormData={setFormData} />
<span> game with at least </span>
<PlayerCount
formData={formData.playerCount}
setFormData={setFormData}
/>
<span> other player(s). My budget is up to: </span>
<SpendSelect
formData={formData.spend}
setFormData={setFormData}
/>
<span> USD</span>
</div>
<div className="flex">
<button type="button"
onClick={fetchOutput}
className="mx-auto px-6 py-2.5 bg-blue-600 text-white font-medium leading-tight rounded shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out text-xl">🎲 Find my game 🎰</button>
</div>
</main>
)
}
CategoriesSelect.jsx
import { useState, useEffect } from 'react';
import axios from 'axios';
const CategoriesSelect = ({formData, setFormData}) => {
const [categories, setCategories] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://api.boardgameatlas.com/api/game/categories?client_id=EsdgqvppMg'
);
setCategories(result.data.categories);
};
fetchData();
}, []);
return (
<div className='inline mb-3 xl:w-96'>
<select className='form-select appearance-none
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding bg-no-repeat
border border-solid border-gray-300
rounded
transition
text-center
ease-in-out
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" aria-label="Default select example'
value={formData}
onChange={e => setFormData({...formData, category: e.target.value})}
>
{categories.map(category => (
<option key={category.id} value={category.id}>
{category.name}
</option>
))}
</select>
</div>
);
};
export default CategoriesSelect;
PlayerCount.jsx
"use client"
export default function PlayerCount({formData, setFormData}) {
const options = [1, 2, 3, 4, 5, 6, 7].map(number => (
<option key={number} value={number}>
{number}
</option>
));
return (
<div className='inline mb-3 xl:w-96'>
<select
value={formData}
onChange={e => setFormData({...formData, playerCount: e.target.value})}
className='form-select appearance-none
px-7
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding bg-no-repeat
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none'
aria-label='Default select example'
>
{options}
</select>
</div> )
}
SpendSelect.jsx
"use client"
export default function SpendSelect({formData, setFormData}) {
const options = [10, 25, 50, 75, 100, 200, 300 ].map(number => (
<option key={number} value={number}>
{number}
</option>
));
return (
<div className='inline mb-3 xl:w-96'>
<select
value={formData}
onChange={e => setFormData({...formData, spend: e.target.value})}
className='form-select appearance-none
px-7
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding bg-no-repeat
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none'
aria-label='Default select example'
>
{options}
</select>
</div> )
}
My challenge:
I'm having trouble updating my formData's state in my Home component from child components. The data.games.length is returning 0 even after updating the props passed from the child components. Can anyone help me with the proper way to update the formData state from its child components?
Fixed! Answer:
before:
onChange={e => setFormData({...formData, playerCount: e.target.value})}
after:
onChange={e => setFormData(prevFormData => ({...prevFormData, playerCount: e.target.value}))}
That should be applied to all components using onChange. It seems that I was spreading a prop instead of an object array.
Related
I have a question and problem with how to show edited text in WYSIWYG textarea. It didn't show up :(
I tried with summernote and ckeditor and always the same, it didn't show up and shows an empty textarea.
Idea is to make a "template" editor where the customer can make a template for example proof for his member that they work for him because of bus tickets or something like that. So, I made a Liveware component that shows up list of templates and when users click on a template from the list they will need to get the previously saved template so they can edit/change if needs something to change. But for some reason, I get only empty textarea if I put summernote or ckeditor and I can't find a reason why that happened. The same is in the database had some info or not.
Here is my component template:
<div>
<div class="px-4 py-3 mb-8 bg-white rounded-lg shadow-md dark:bg-gray-800">
<label class="block text-sm">
<span class="text-gray-700 dark:text-white">{{__('site.team_member_document.document_type')}}</span>
<select class="block w-full mt-1 text-sm"
name="team_member_document_type_id" id="team_member_document_type_id"
wire:model="team_member_document_type_id" wire:change="onChangeDocumentType()">
<option value="">{{__('site.team_member_document.select_document_type')}}</option>
#foreach($document_types as $item)
<option value="{{$item['id']}}"
#if(old('team_member_document_type_id')==$item['id']) selected #endif
>{{$item['name']}}</option>
#endforeach
</select>
</label>
<label class="block text-sm" wire:ignore>
<span class="text-gray-700 dark:text-white">{{__('site.team_member_document.template')}}</span>
<textarea name="template" id="template" wire:model.defer="template">{{ $template }}</textarea>
</label>
<label class="block mt-4 text-sm">
<button type="button" wire:click="submitForm()"
class="px-4 py-2 text-sm font-medium">
{{__('site.save')}}
</button>
<a href="{{route('team_member_document.index')}}"
class="px-4 py-2 text-sm font-medium">
{{__('site.cancel')}}
</a>
</label>
</div>
<script>
$(function () {
$('#template').summernote({
placeholder: '',
height: 300,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link']],
['view', ['fullscreen', 'codeview']]
],
callbacks: {
onChange: function (contents, $editable) {
#this.set('template', contents);
}
}
});
})
</script>
and here is Livewire component code:
namespace App\Http\Livewire;
use Livewire\Component;
class TeamMemberDocumentTemplate extends Component
{
public $document_types;
public $team_member_document_type_id;
public $template;
protected array $rules = [
'template' => 'required|min:30',
];
public function mount($document_types)
{
$this->template = '';
$this->document_types = $document_types;
}
public function render()
{
return view('livewire.team-member-document-template');
}
public function onChangeDocumentType()
{
$this->template = $this->document_types->filter(function ($item) {
return ($this->team_member_document_type_id == $item->id);
})->first()->template ?? '';
}
public function submitForm()
{
$this->validate();
$document_type = $this->document_types->filter(function ($item) {
return ($this->team_member_document_type_id == $item->id);
})->first();
$document_type->update([
'template' => $this->template
]);
return redirect()->route('team_member_document.index');
}
}
When adding this part of the code into livewire.team-member-document-template.blade.php all works well:
When adding this part of the code into livewire.team-member-document-template.blade.php all works well:
<script> $(function () { $('#summernote_small').on('summernote.change', function (we, contents, $editable) { #this.set('print_note', contents); }); }) </script>
Created ckeditor 5 component separately and included other component
import React from "react";
import EditorCustom from "ckeditor5-custom-build/build/ckeditor";
import { CKEditor } from "#ckeditor/ckeditor5-react";
import { fileStorage } from "../../../firebase/firebase.config";
import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
class MyUploadAdapter {
constructor(loader) {
this.loader = loader;
}
// Starts the upload process.
upload() {
return this.loader.file.then(
(file) =>
new Promise((resolve, reject) => {
let storage = fileStorage;
uploadBytes(ref(storage, file.name), file)
.then((snapshot) => {
return getDownloadURL(snapshot.ref);
})
.then((downloadURL) => {
resolve({
default: downloadURL,
});
})
.catch((error) => {
reject(error.message);
});
})
);
}
}
const editorConfiguration = {
ui: {
viewportOffset: {
top: 56,
},
},
toolbar: {
items: [
"undo",
"redo",
"|",
"heading",
"fontFamily",
"fontSize",
"fontBackgroundColor",
"fontColor",
"highlight",
"bulletedList",
"numberedList",
"todoList",
"|",
"imageUpload",
"imageInsert",
"insertTable",
"mediaEmbed",
"link",
"pageBreak",
"-",
"outdent",
"indent",
"|",
"blockQuote",
"bold",
"italic",
"underline",
"strikethrough",
"horizontalLine",
],
shouldNotGroupWhenFull: true,
},
language: "en",
image: {
toolbar: [
"imageTextAlternative",
"toggleImageCaption",
"imageStyle:inline",
"imageStyle:block",
"imageStyle:side",
"linkImage",
],
},
table: {
contentToolbar: [
"tableColumn",
"tableRow",
"mergeTableCells",
"tableCellProperties",
"tableProperties",
],
},
};
const Editor = ({ value, onChange }) => {
return (
<>
<CKEditor
editor={EditorCustom}
config={editorConfiguration}
onReady={(editor) => {
editor.plugins.get("FileRepository").createUploadAdapter = (
loader
) => {
return new MyUploadAdapter(loader);
};
}}
data={value}
onChange={(event, editor) => {
const data = editor.getData();
onChange(data);
}}
/>
</>
);
};
export default Editor;
but when i include component in create.js other default inputs delay and ckeditor input delay too, if not use useState ckeditor working fine
import { useEffect, useState } from "react";
import dynamic from "next/dynamic";
import { database } from "../../../firebase/firebase.config";
import { collection, addDoc } from "firebase/firestore";
const CreateBlog = () => {
const Editor = dynamic(() => import("../../dashboard/utils/myEditor"), {
ssr: false,
});
const [title, setTitle] = useState("");
const [subTitle, setSubTitle] = useState("");
const [message, setMessage] = useState("");
const [body, setBody] = useState("");
const databaseRef = collection(database, "blogs");
const addData = () => {
addDoc(databaseRef, {
title: title,
sub_title: subTitle,
message: message,
})
.then(() => {
alert("Data Sent");
// getData();
setTitle("");
setSubTitle("");
setMessage("");
})
.catch((err) => {
console.error(err);
});
};
return (
<>
<div className="w-full px-4">
<div className="w-full p-8 mt-10 bg-white rounded-lg shadow-md lg:w-3/3 md:w-2/2 md:ml-auto md:mt-0">
<h2 className="mb-1 text-lg font-medium text-gray-900 title-font">
Create Post
</h2>
<div className="mb-4 ">
<label htmlFor="titile" className="text-sm leading-7 text-gray-600">
Title
</label>
<input
type="title"
id="title"
name="title"
value={title}
onChange={(event) => setTitle(event.target.value)}
className="w-full px-3 py-1 text-base leading-8 text-gray-700 transition-colors duration-200 ease-in-out bg-white border border-gray-300 rounded outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200"
/>
</div>
<div className="mb-4">
<label htmlFor="titile" className="text-sm leading-7 text-gray-600">
Sub Title
</label>
<input
type="title"
id="title"
name="title"
value={subTitle}
onChange={(event) => setSubTitle(event.target.value)}
className="w-full px-3 py-1 text-base leading-8 text-gray-700 transition-colors duration-200 ease-in-out bg-white border border-gray-300 rounded outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200"
/>
</div>
<div className="relative mb-4">
<label
htmlFor="message"
className="text-sm leading-7 text-gray-600"
>
Message
</label>
<textarea
id="message"
name="message"
value={message}
onChange={(event) => setMessage(event.target.value)}
className="w-full h-32 px-3 py-1 text-base leading-6 text-gray-700 transition-colors duration-200 ease-in-out bg-white border border-gray-300 rounded outline-none resize-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200"
></textarea>
</div>
<div className="mb-4 ">
<label htmlFor="body" className="text-sm leading-7 text-gray-600">
Body
</label>
<Editor value={body} onChange={(value) => setBody(value)} />
</div>
<button
onClick={addData}
className="px-6 py-2 text-lg text-white bg-blue-500 border-0 rounded focus:outline-none hover:bg-blue-600"
>
Button
</button>
</div>
</div>
</>
);
};
export default CreateBlog;
<Editor value={body} onChange={(value) => setBody(value)} />
used useState but its delay and slow breaking input type
how to use ckeditor with other inputs and value set useState without dealy
I have a Vuejs 3 dropdown reusable component. My problem is that the #foreach statement runs before the component loads so it causes a flash of the foreach results which is very ugly upon refresh or when the page is loading.
To demonstrate please check this gif:
My component in blade:
<Dropdown title="{{ isset($currentCategory) ? ucwords($currentCategory->name) : 'Categories' }}">
<Dropdowncontent>
<Dropdownitems href="/">
All
</Dropdownitems>
<div>
#foreach ($categories as $category)
<Dropdownitems
href="/?category={{ $category->slug }}&{{ http_build_query(request()->except('category')) }}"
class="{{ isset($currentCategory) && $currentCategory->is($category) ? ' selectedCategoryItem' : '' }}">
{{ $category->name }}
</Dropdownitems>
#endforeach
</div>
</Dropdowncontent>
</Dropdown>
I added a div to contain the #foreach statement but i don't know what to do from here. I don't want to use alpineJS as it will defeat the purpose of using Vue (I guess?).
I just need a way to only display this div or the #foreach statement if the component is fully loaded or if the button is pressed or something like that. Any ideas?
-- EDIT --
I tried to hide the links in my 'dropdownitems' vue component and set the default value to false. The links are now hidden but still the blade #foreach statement echoing out the results as text before the component is loaded:
<template>
<a v-if="showLinks" href="" class="demogard categoryItems">
<slot />
</a>
</template>
<script>
export default {
name: "Dropdownitems",
setup() {
const showLinks = false;
return {
showLinks,
};
},
};
</script>
<style></style>
Here is a gif to show the result of that:
-- EDIT --
Here is my dropdown component:
<template>
<div
class="relative"
v-click-outside="onClickOutside"
#click="showCategories"
>
<slot name="toggler">
<button
class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9 text-sm font-semibold lg:inline-flex lg:w-32"
>
{{ title }}
</button>
</slot>
<slot />
</div>
</template>
<script>
import vClickOutside from "click-outside-vue3";
import { ref, onMounted, provide } from "vue";
export default {
name: "Dropdown",
props: ["title"],
directives: {
clickOutside: vClickOutside.directive,
},
setup() {
const sharedState = ref(false);
const showCategories = () => {
sharedState.value = !sharedState.value;
};
const onClickOutside = (event) => {
sharedState.value = false;
};
provide("sharedState", sharedState);
return {
sharedState,
showCategories,
onClickOutside,
};
},
};
</script>
<style></style>
As your question, I think you have to add if condition on your dropdown component.
Your dropdown component should be like this
#dropdown.vue
<template>
<div class="dropdown">
<div #click="show = !show">{{title}}</div>
<div v-if="show">
<slot />
</div>
</div>
</template>
<script>
import { ref } from "vue";
export default {
props: ["title"],
setup(props) {
const show = ref(false);
return {
show,
};
},
};
</script>
Demo
---- EDIT ----
#dropdown.vue
<template>
<div
class="relative"
v-click-outside="sharedState = false"
>
<slot name="toggler">
<button
class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9 text-sm font-semibold lg:inline-flex lg:w-32"
#click="sharedState = !sharedState"
>
{{ title }}
</button>
</slot>
<div v-if="sharedState">
<slot />
</div>
</div>
</template>
<script>
import vClickOutside from "click-outside-vue3";
import { ref, onMounted, provide } from "vue";
export default {
name: "Dropdown",
props: ["title"],
directives: {
clickOutside: vClickOutside.directive,
},
setup() {
const sharedState = ref(false);
// const showCategories = () => {
// sharedState.value = !sharedState.value;
// };
// const onClickOutside = (event) => {
// sharedState.value = false;
// };
provide("sharedState", sharedState);
return {
sharedState,
//showCategories,
//onClickOutside,
};
},
};
</script>
<style></style>
Try with a #if directive:
Conditional Rendering
from the documentation:
<button #click="awesome = !awesome">Toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
As showed in the example it render the "h1" tag conditionally respect the "awesome" variable.
In this case i will set a default value of "false" and i will turn it to "true" in the mounted hook:
Lifecycle
It's impossible to load Vue before PHP because your webpage only displays when full PHP code is received from the server. Therefore, we're never able to stop PHP or HTML from flashing if we're using them inside a reusable Vue component.
The solution I made is simply passing the value of the foreach loop as a prop to the Vue component in order for it to be displayed from there, not from my blade file.
Here's my code in blade after passing the value of the category name as a prop to my Vue component.
<Dropdown title="{{ isset($currentCategory) ? ucwords($currentCategory->name) : 'Categories' }}">
<Dropdowncontent>
<Dropdownitems href="/" category="All"></Dropdownitems>
#foreach ($categories as $category)
<Dropdownitems
category="{{ $category->name }}"
href="/?category={{ $category->slug }}&{{ http_build_query(request()->except('category')) }}"
class="{{ isset($currentCategory) && $currentCategory->is($category) ? ' selectedCategoryItem' : '' }}">
</Dropdownitems>
#endforeach
</Dropdowncontent>
</Dropdown>
Here is me displaying it from there the Vue dropdown items component:
<template>
<a href="" class="demogard categoryItems">
<slot>{{ category }}</slot>
</a>
</template>
<script>
export default {
name: "Dropdownitems",
props: ["category"],
};
</script>
<style></style>
Hi there I am not able to load link from graphCMS pls help
trying to render hyperlink content from the graphCMS post but it is not appearing on the post details page on blog.
here is my code
import React from "react";
import moment from "moment";
const PostDetail = ({ post }) => {
const getContentFragment = (index, text, obj, type) => {
let modifiedText = text;
if (obj) {
if (obj.bold) {
modifiedText = <b key={index}>{text}</b>;
}
if (obj.italic) {
modifiedText = <em key={index}>{text}</em>;
}
if (obj.underline) {
modifiedText = <u key={index}>{text}</u>;
}
}
switch (type) {
case "heading-three":
return (
<h3 key={index} className="text-xl font-semibold mb-4">
{modifiedText.map((item, i) => (
<React.Fragment key={i}>{item}</React.Fragment>
))}
</h3>
);
case "paragraph":
return (
<p key={index} className="mb-8">
{modifiedText.map((item, i) => (
<React.Fragment key={i}>{item}</React.Fragment>
))}
</p>
);
case "heading-four":
return (
<h4 key={index} className="text-md font-semibold mb-4">
{modifiedText.map((item, i) => (
<React.Fragment key={i}>{item}</React.Fragment>
))}
</h4>
);
case "image":
return (
<img
key={index}
alt={obj.title}
height={obj.height}
width={obj.width}
src={obj.src}
/>
);
case "link":
return (
<a {...index} href={obj.url}>
{modifiedText.map((item, i) => (
<React.Fragment key={i}>{item}</React.Fragment>
))}
</a>
);
default:
return modifiedText;
}
};
return (
<div className="bg-white shadow-lg rounded-lg lg:p-8 pb-12 mb-8">
<div className="relative overflow-hidden shadow-md mb-6">
<img
src={post.featuredImage.url}
alt={post.title}
className="objecy-top h-full w-full rounded-t-lg"
/>
</div>
<div className="px-4 lg:px-0">
<div className="flex items-center mb-8 w-full">
<div className="flex items-center mb-4 lg:mb-0 w-full lg:w-auto mr-8">
<img
className="align-middle rounded-full"
src={post.author.photo.url}
alt={post.author.name}
height="30px"
width="30px"
/>
<p className="inline align-middle text-gray-700 ml-2 text-lg font-medium">
{post.author.name}
</p>
</div>
<div className="font-medium text-gray-700">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 inline mr-2 text-pink-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<span className="align-middle">
{moment(post.createdAt).format("MMM DD, YYYY")}
</span>
</div>
</div>
<h1 className="mb-8 text-3xl font-semibold">{post.title}</h1>
{post.content.raw.children.map((typeObj, index) => {
const children = typeObj.children.map((item, itemindex) =>
getContentFragment(itemindex, item.text, item)
);
return getContentFragment(index, children, typeObj, typeObj.type);
})}
</div>
</div>
);
};
export default PostDetail;
everything other than link is appearing on the page but not hyperlink content from the graphcms
thanks in advance !
If you console.log raw data you can see that the 'link' types are contained in 'paragraph' types, so the code will never enter the case 'link'.
GraphCMS provide a lib to easyly render Rich Text. May be a good option for what you want.
What you have done here is map through the modifiedText array, but hyperlinks are not stored in that same way as the text.
Your code should look something like this:
case "link":
return (
<a key={index} href={obj.href} className='text-md text-blue-700'>
<React.Fragment>{obj.title}</React.Fragment>
</a>
);
Added some styling there to give the link a blue color.
I am working on reactjs 5.X version. I am writing UT with enzyme. Below is my reusable component with prop arguments. Not able to find the div tags inside of the const component.Can you help me how to get the div tags using classname or using find function to get div tags.
import React from 'react';
import styles from './democheck.css';
const democheck = ({ input, cb,
required, testCheckbox, checked, label, meta: { error } }) => (
<div id="hierrdivid" className={styles.testDivColumn}>
<div className={styles.testDiv}>
<br />
<span className={styles.testLabel}>
{label}
</span>
{required && <span className={styles.error}>
*
</span>}
<input
{...input}
name={`form-field-${input.name}`}
checked={checked}
id={input.name}
className={testCheckbox ? styles.testCheckboxError :
styles.testCheckbox}
type="checkbox"
onChange={() => {
if (cb) {
cb(document.getElementById(input.name).checked);
}
}}
/>
</div>
<div className={styles.testerrorDiv}>
{testCheckbox &&
<div className={styles.testerrorLabel}>
{label} {error}
</div>}
</div>
</div>
);
democheck.propTypes = {
input: React.PropTypes.objectOf(React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.func
])),
cb: React.PropTypes.func,
label: React.PropTypes.string,
meta: React.PropTypes.shape({}),`enter code here`
required: React.PropTypes.bool,
checked: React.PropTypes.bool,`enter code here`
testCheckbox: React.PropTypes.bool
};