I have a bunch of filtering components that developers can use. For example TextFilter.js, OptionsFilter.sj, NumericFilter.js
And this is the code of TextFilter.js
import TextField from '#material-ui/core/TextField';
import { useState } from 'react';
const TextFilter = ({ column, placeholder }) => {
const [value, setValue] = useState('');
return <TextField
onChange={(event, value) => setValue(event.target.value)}
lable={placeholder}
/>
};
export default TextFilter;
Developers use it this way:
import List from '../../Components/Layouts/List';
import TextFilter from '../../Components/Filters/TextFilter';
import NumericFilter from '../../Components/Filters/NumericFilter';
const filters =
<>
<TextFilter column='title' placeholder='Title' />
<NumericFilter column='age' placeholder='Age' min={20} max={130} />
</>
cons SampleList = (props) => {
return (
<ListComponent
filters={filters}
/>
);
};
Now I'm stuck on how to extract values from these filters. How can I extract values?
You should handle child's value in it's parent:
child:
import TextField from "#material-ui/core/TextField";
const TextFilter = ({ column, placeholder, changed }) => {
return (
<TextField
onChange={(event) => changed(event.target.value)}
placeholder={placeholder}
/>
);
};
export default TextFilter;
parent:
import TextFilter from "./TextFilter";
export default function App() {
const handleChanged = (value) => {
console.log(value);
};
return (
<div className="App">
<TextFilter
column="title"
placeholder="Title"
changed={(value) => handleChanged(value)}
/>
</div>
);
}
Related
I have a function that selects a country from a dropdown. I have put it in a file by itself. And then on my Dashboard.js I just call the funtion to appear. But how can I get the value from the Dashboard.js?
CountrySelector.js
import React, { useState, useMemo } from 'react'
import Select from 'react-select'
import countryList from 'react-select-country-list'
function CountrySelector() {
const [value, setValue] = useState("")
const options = useMemo(() => countryList().getData(), [])
const changeHandler = value => {
setValue(value)
}
const style = {
display: "inline-block",
width: "300px"
};
return <div style={style}><Select options={options} value={value} onChange={changeHandler} /></div>
}
export default CountrySelector;
Dashboard.js
import CountrySelector from '../util/CountrySelector';
const Dashboard = () => {
return(
<div>
<CountrySelector/>
</div>
);
};
export default Dashboard;
I know props doesn't work because you pass data from parent to the child. And I want to pass data from child to the parent. Any help is appreciated.
Put your state in your parent component, and pass them as props to your child component
import { useState, useMemo } from 'react';
import CountrySelector from '../util/CountrySelector';
import countryList from 'react-select-country-list';
const Dashboard = () => {
const [value, setValue] = useState('');
const options = useMemo(() => countryList().getData(), []);
return (
<div>
<CountrySelector value={value} setValue={setValue} options={options} />
</div>
);
};
export default Dashboard;
import Select from 'react-select';
function CountrySelector({ value, setValue, options }) {
const style = {
display: 'inline-block',
width: '300px',
};
return (
<div style={style}>
<Select options={options} value={value} onChange={setValue} />
</div>
);
}
export default CountrySelector;
I have some problems with final-form. function handleSubmit don't calls anything. I checked official final-form example. I do identically that written there. But it's not working.
Here my form code:
import React, {FunctionComponent} from 'react';
import {Field, Form} from 'react-final-form';
import {IAddComponentProps} from "./interfaces";
import {EditContainer, StyledButton} from './styles';
import EditInput from "../EditInput";
const AddComponent: FunctionComponent<IAddComponentProps> = ({onSubmitForm, onEditInput}) => {
return (
<Form
onSubmit={onSubmitForm}
render={({handleSubmit}) => (
<EditContainer onSubmit={handleSubmit}>
<Field name={'addComment'}>
{({input}) => (
<EditInput {...input} onEditInput={onEditInput}/>
)}
</Field>
<StyledButton>OK</StyledButton>
</EditContainer>
)}
/>
)
};
export default AddComponent;
Here is my functions which I put into props:
const onChangeInput = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value)
}
const onSubmitAddComment = (event: React.ChangeEvent<HTMLFormElement>) => {
const newComment: ICommentsData = {
id: new Date().getMilliseconds(),
cardId: cardId,
name: author,
comment: inputValue
}
event.preventDefault();
event.target.reset()
dispatch(actions.comments.addComment({newComment}))
resetInputValue()
}
The reason of this was, that i put into onSubmit of Form function from props. When i created function inside component it started working. So new code of my form is:
import React, {FunctionComponent} from 'react';
import {Field, Form} from 'react-final-form';
import {IAddComponentProps} from "./interfaces";
import {EditContainer, StyledButton} from './styles';
import EditInput from "../EditInput";
const AddComponent: FunctionComponent<IAddComponentProps> = ({onSubmitForm, onEditInput}) => {
const onSubmit = () => {
onSubmitForm()
}
return (
<Form
onSubmit={onSubmit}
render={({handleSubmit,form}) => (
<EditContainer onSubmit={(event) => {
event.preventDefault()
handleSubmit()
form.reset()
}}>
<Field name={'addComment'}>
{({input}) => (
<EditInput {...input} onEditInput={onEditInput}/>
)}
</Field>
<StyledButton>OK</StyledButton>
</EditContainer>
)}
/>
)
};
export default AddComponent;
I want to share Child Component (Product.js) data into Parent Component (App.js) without button click. I will use useState with context API. I don't know how to passed this data without click event.
Product.js data display into console.log() into App.js component.
App.js
import React from 'react';
import Product from './Product';
function App() {
return (
<div className="App">
<Product />
</div>
);
}
export default App;
Product.js
import React from 'react';
const Product = () => {
return (
<div>
Product Name: <input type="text" />
<br />
Description:- <input type="text" />
</div>
)
}
export default Product
Please help I have no advance knowledge of react.
There are three ways to share information without click event with useContext and useState.
useContext
useState in childComponent
useState in parentComponent
1. useContext
import { createContext, useContext, useState } from 'react';
import React from 'react';
const Context = createContext();
const Product = () => {
const [info, setInfo] = useContext(Context);
return (
<div>
Product Name: <input type="text" value={info.name} onChange={(e) => {
setInfo({ ...info, name: e.target.value });
}} />
<br />
Description:- <input type="text" value={info.desc} onChange={(e) => {
setInfo({ ...info, desc: e.target.value });
}} />
</div>
);
}
function App() {
const [info, setInfo] = useState({
name: '',
desc: ''
});
return (
<div className="App">
<Context.Provider value={[info, setInfo]}>
<Product />
</Context.Provider>
</div>
);
}
export default App;
If you have each component in a file. You have to create the context in a third file and import it from the parent and child component.
2. useState in childComponent
import { useEffect, useState } from 'react';
import React from 'react';
const Product = ({ setParentInfo }) => {
const [info, setInfo] = useState({ name: '', desc: '' });
useEffect(() => {
setParentInfo(info);
}, [info])
return (
<div>
Product Name: <input type="text" value={info.name} onChange={(e) => setInfo({ ...info, name: e.target.value })} />
<br />
Description:- <input type="text" value={info.desc} onChange={(e) => setInfo({ ...info, desc: e.target.value })} />
</div>
)
}
let info = { name: '', desc: '' }
function App() {
return (
<div className="App">
<Product setParentInfo={(newInfo) => {
info = { ...newInfo };
}} />
</div>
);
}
export default App;
3. useState in parentComponent
import { useState } from 'react';
import React from 'react';
const Product = ({ info, setParentInfo }) => {
return (
<div>
Product Name: <input type="text" value={info.name} onChange={(e) => setParentInfo({ ...info, name: e.target.value })} />
<br />
Description:- <input type="text" value={info.desc} onChange={(e) => setParentInfo({ ...info, desc: e.target.value })} />
</div>
)
}
function App() {
const [info, setInfo] = useState({ name: '', desc: '' });
console.log("parent: ", info);
return (
<div className="App">
<Product info={info} setParentInfo={(newInfo) => {
setInfo({ ...newInfo });
}} />
</div>
);
}
export default App;
I hope I've helped you. Have a nice day!
If its a direct child to parent communication, it's better to done this using props. Less code, works fine!
App.js:-
import React from 'react';
import Product from './Product';
function App() {
return (
<div className="App">
<Product
onProductNameChange={productName => console.log(productName)}
onProductDescChange={productDesc => console.log(productDesc)}
/>
</div>
);
}
export default App;
Product.js:-
import React from 'react';
const Product = ({onProductNameChange, onProductDescChange}) => {
return (
<div>
Product Name: <input type="text" onChange={e => onProductNameChange(e.target.value)} />
<br />
Description:- <input type="text" onChange={e => onProductDescChange(e.target.value)} />
</div>
)
}
export default Product
Share information without click event with useContext and useState.
App.js
import React from 'react';
import Store from './Store';
import ProductList from './ProductList';
function App() {
return (
<div className="App">
<Store>
<ProductList />
</Store>
</div>
);
}
export default App;
ProductList.js
import React, { useContext } from 'react';
import { Context } from './Store';
import Product from './Product';
import AddProduct from './AddProduct';
const ProductList = () => {
const [state, setState] = useContext(Context);
console.log(state);
return (
<>
<AddProduct />
<Product />
</>
)
}
export default ProductList
AddProduct.js
import React, { useContext} from 'react';
import { Context} from './Store';
const AddProduct = () => {
const [products, setProducts] = useContext(Context);
return (
<div>
Description:- <input type="text"
onChange={(e) => setProducts({ ...products, Description: e.target.value })}/>
</div>
)
}
export default AddProduct
Product.js
import React, { useContext} from 'react';
import { Context} from './Store';
const Product = () => {
const [products, setProducts] = useContext(Context);
return (
<>
<h2>Product</h2>
<p>Description: {products.Description}</p>
</>
)
}
export default Product
Store.js
import React, { useState } from 'react';
const product = {
Description: '',
};
export const Context = React.createContext();
const Store = ({ children}) => {
const [products, setProducts] = useState(product);
return (
<Context.Provider value={[products, setProducts]}>{children}</Context.Provider>
);
};
export default Store;
I have a two Input form and a Paragraph, when I try to change the value of input the paragraph get updated, once the paragraph is updated I am trying to edit the paragraph with the help of drafts library, but once I update the paragraph and save it, it doesn't update the paragraph.
Please anyone Help me out to solve the problem
Codesandbox Link : Code
Context API
import React, { useState, createContext } from "react";
export const Contx = createContext();
export const ConProvider = ({ children }) => {
const [customerName, setCustomerName] = useState("");
const [amount, setAmount] = useState("");
const defaultValue = `<p>Hello ${
customerName === "" ? "User" : customerName
},</p>
<p>Please Click on the link below to pay the order - <strong>${amount}</strong> . </p>
<p>Click hear to pay</p>
<br/>
<p>Thanks and Regards</p>
<p>testUser</p>`;
const [draftValue, setDraftValue] = useState(defaultValue);
return (
<Contx.Provider
value={{
defaultValue,
setCustomerName,
setAmount,
customerName,
amount,
setDraftValue,
draftValue
}}
>
{children}
</Contx.Provider>
);
};
homePage
import React, { useContext, useState } from "react";
import ReactDOM from "react-dom";
import { ConProvider, Contx } from "../ContextApi";
import Data from "./Component/Data/Data";
import NewDraft from "./Component/Data/NewDraft";
import Modal from "./Component/Data/Modal";
import "./styles.css";
function App() {
const { defaultValue, setDraftValue, draftValue } = useContext(Contx);
// console.log("defaultValue", defaultValue);
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div className="App">
<Data />
<Modal handleClose={handleClose} show={show}>
<NewDraft
prsFunc={setDraftValue}
handleClose={handleClose}
defaultValueEmpty={false}
defaultValue={defaultValue}
/>
</Modal>
<div
className="templateStyle p-2"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: draftValue && draftValue
}}
/>
<button onClick={handleShow}>Edit</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<ConProvider>
<App />
</ConProvider>,
rootElement
);
Input Form
import React, { useContext } from "react";
import { Contx } from "../../../ContextApi";
export default function Data() {
const {
setCustomerName,
setDraftValue,
defaultValue,
setAmount,
customerName,
amount
} = useContext(Contx);
React.useEffect(() => {
setDraftValue(defaultValue);
});
// console.log("fffffff", customerName, amount);
return (
<div>
<input
type="text"
value={customerName}
name="customerName"
placeholder="Enter Customer name"
onChange={(e) => {
setCustomerName(e.target.value);
}}
/>
<input
type="number"
placeholder="Enter Amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
</div>
);
}
DraftJS
import React, { useState } from "react";
import { Editor } from "react-draft-wysiwyg";
import {
EditorState,
convertToRaw,
ContentState,
convertFromHTML
} from "draft-js";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import draftToHtml from "draftjs-to-html";
import "./Data.css";
export default function NewDraft({
handleClose,
defaultValue,
defaultValueEmpty,
prsFunc
}) {
const initialState = defaultValueEmpty
? () => EditorState.createEmpty()
: EditorState.createWithContent(
ContentState.createFromBlockArray(convertFromHTML(defaultValue))
);
const [editorState, setEditorState] = useState(initialState);
const onChange = (value) => {
setEditorState(value);
};
const saveData = () => {
prsFunc(draftToHtml(convertToRaw(editorState.getCurrentContent())));
handleClose();
};
// console.log(draftToHtml(convertToRaw(editorState.getCurrentContent())));
return (
<div>
<div style={{ border: "2px solid", padding: "20px" }}>
<Editor
editorState={editorState}
toolbarClassName="toolbarClassName"
wrapperClassName="wrapperClassName"
editorClassName="editorClassName"
onEditorStateChange={(value) => onChange(value)}
/>
<button variant="secondary" onClick={saveData}>
Save
</button>
</div>
</div>
);
}
The problem you are facing is caused by this line in Data component. Every time the component is updated, the draftValue is set to the defaultValue.
React.useEffect(() => {
setDraftValue(defaultValue);
});
I would like to implement Algolia search with Ant Design Autocomplete. But I get Cannot read property 'focus' of null error when I try to extract the SearchInput component (without extraction, i. e. when I leave it in the same file, it works fine). Here is the working code:
import React, { useState } from 'react'
import { AutoComplete, Input } from 'antd'
const SearchAutocomplete = connectAutoComplete(
({ hits, currentRefinement, refine }) => {
...
return (
<AutoComplete
options={options}
onSelect={onSelect}
onSearch={handleSearch}
open={open}
>
<Input
value={currentRefinement}
onChange={e => refine(e.currentTarget.value)}
/>
</AutoComplete>
);
}
);
But when I move Input to a separate component like this it doesn't work:
import React, { useState } from 'react'
import { AutoComplete } from 'antd'
import SearchInput from './SearchInput'
const SearchAutocomplete = connectAutoComplete(
({ hits, currentRefinement, refine }) => {
...
return (
<AutoComplete
options={options}
onSelect={onSelect}
onSearch={handleSearch}
open={open}
>
<SearchInput value={currentRefinement} onChange={e => refine(e.currentTarget.value)}/>
</AutoComplete>
);
}
);
And the SearchInput component itself:
import React from 'react'
import { Input } from 'antd'
const SearchInput = props => {
const { value, onChange} = props;
return (
<Input
value={value}
onChange={onChange}
/>
)
}
Here is the link to codesandbox with the extracted component. How can I fix this error?
Adding React.forwardRef() to SearchInput solved the issue:
const SearchInput = React.forwardRef((props, ref) => {
const { onChange } = props;
return (
<Input.Search
onChange={onChange}
ref={ref}
/>
)
})