React hook form with customize controller - react-select

<Controller
name={'productType'}
control={props.control}
render={({ field: { value, onChange, onBlur } }) => {
return (
<SelectInput
options={productTypeOption}
label={'Product Type'}
isDisabled={isDisabled.productTypeDisable}
onChange={onProductTypeChange}
isLoading={isLoading.productType}
statusMsg={productTypeOption.length}
/>
)}}>
</Controller>
I got my select input componenet from react-select package and i want to use react hook form controller with it btw i already got my own onChange props on it , In docs to send data to useForm i also need to put field onchange on it so how to bring onChange useForm with my own logic???
const onProductTypeChange = (e) => {
setServiceOtherOption([])
setServiceQuantitesOption([])
const valueSelect = e.value
props.setJobData((arr) => ({
...arr,
productType: valueSelect
}
))
}
this is my on change needed

You can set onChange prop on SelectInput as a function which calls your onProductTypeChange function and also call onChange of react-hook-form, like this:
<SelectInput
onChange={(e)=> {
onProductTypeChange(e);
onChange(e.value);
}}
...
/>

Related

specific ID in react-admin list

would like to get the id of a row when I click on a button or somewhere on the row inside the list/Datagrid component of react-admin,
I am completely new to react js and react-admin as well.
WOuld appreciate for any kind gesture
React-admin exposes a hook called useRecordContext that lets you access the record used by the current component. In a Datagrid, this lets you access the record of the row.
So you can create a component like so:
import { useRecordContext } from 'react-admin';
const MyButton = () => {
const record = useRecordContext();
const handleClick = () => {
// the current row id is record.id
// do something with it
};
return <button onClick={handleClick}>Do stuff</button>;
}
Then, use that component as a child of <Datagrid>:
const MyList = () => (
<List>
<Datagrid>
<TextField source="title" />
<MyButton />
</Datagrid>
</List>
);
More information at https://marmelab.com/react-admin/useRecordContext.html

How to store coming data persistently?

I use react-native.
And this is the function that I want to use.
The most important point here is editCommentMutation.
In order to execute this mutation, it requires two variables which are id and payload.
const onUpdateComment = React.useCallback((commentId) => {
setEdit(true);
console.log(commentId, comments);
editCommentMutation({
variables: {
id: parseInt(commentId),
payload: comments,
},
});
}, []);
I get these two variables correctly.
For id , I get it from component screen. So It comes thru argument.
For payload, I get it on the same screen.
Problem here is when I press button1, it sends commentId(id) data from component screen to this page.
And when I press button2, it sends comments(payload) data on this page.
On this App, I press button1 and write comments then button2 in order.
So Each data comes not together, but one by one.
So I execute console.log(commentId, comments),
press button1 : 386 undefined
press button2 : undefined Object { "comments": "뭐야", }
It has undefined for sure..
But in order to execute mutation, I need two data together.
For this, I need to save coming data in somewhere, I guess.
I also tried
const [data, setData] = useState("").
After I save coming commentId to here as:
setData(commentId).
But it isn't saved, just disappears. :)
Can you help me?
Here is a minimal verifiable example. Run the code below and
click ✏️ to edit one of the comments
click ✅ to save your edit and view the updated comment
function App() {
const [edit, setEdit] = React.useState(null)
const [comments, setComments] = React.useState([ "hello", "안녕하세요" ])
const onEdit = editable => event => { setEdit(editable) }
const onUpdate = newComment => event => {
/* execute your graphql mutation here */
setComments([
...comments.slice(0, edit.index),
newComment,
...comments.slice(edit.index + 1)
])
setEdit(null)
}
return <div>
{comments.map((comment, index) =>
<p>{comment}
<button
children="✏️"
onClick={onEdit({comment, index})}
disabled={Boolean(edit)}
/>
</p>
)}
{edit ? <EditComment text={edit.comment} onUpdate={onUpdate} /> : null}
</div>
}
function EditComment({ text, onUpdate }) {
const [value, setValue] = React.useState(text)
return <div>
<input value={value} onChange={e => setValue(e.target.value)} />
<button onClick={onUpdate(value)} children="✅" />
</div>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
button[disabled] { opacity: 0.5; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
In your App you will execute your mutation in onUpdate. A cancel button ❌ can easily be defined using const onCancel = event => { setEdit(null) } and pass it to EditComment.

How to find component, passed as slot into child component, in jest?

I have a component, that uses another 'wrapper' component and passing all of it's body as slots into it.
Something like that:
<template>
<WrapperComponent>
<Card />
</WrapperComponent>
</template>
Question is - how do I find this 'Card' component while testing parent component in jest?
Have tried like that, but failed:
describe('RegistrationModal', () => {
const wrapper = mount(RegistrationModal, {
localVue
});
test('Registration of private company', async () => {
const PrivateCard = wrapper.findAllComponents(Card).at(0);
await PrivateCard.trigger('click', ['private'] );
expect(wrapper.vm.action).toBe('private');
expect(wrapper.vm.step).toBe(1);
});
});

how do I pass ref to state?

I created a ref and passed it to the component as an argument. Now how can I write it to State without dispatch?
const myRef = createRef<any>();
const KeyboardAvoidingWrapper: React.FC<IKeyboardAvoidingProps> = (
props: IKeyboardAvoidingProps,
=> {
if (isAndroid) {
return (
<ScrollView ref={myRef} style={styles.scroll} contentContainerStyle={styles.scrollContent}>
<KeyboardAvoiding>{props.children}</KeyboardAvoiding>
</ScrollView>
);
}
This example might help you.
<Component ref={(ref) => {
// You can now write ref to state,
// which I will not recommend
// or pass it to callback
props.getInnerRef(ref);
}} />
// You need to pass getInnerRef
<Component getInnerRef={(ref) => {
this.innerRef = ref;
}}
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
Please refer the react documentation. It clearly defines how to use refs.
ForwadingRefs

How to initiliaze data with props value without call the props in template?

I have props structured like this.
props: {
propsChooseColor: {
type: String,
required: true
}
}
The props received as expected(checked with vue devtools).
And then I try to initialize data with the props value like the official suggestion.
chooseColor: this.propsChooseColor
The problem is :
If I call chooseColor and propsChooseColor in template, the
chooseColor have same value as the props.
But if I don't call propsChooseColor, the chooseColor value is "".
E.g Value of chooseColor will empty.
<template>
...
data color: {{ chooseColor }} // RETURN ""
...
</template>
E.g Value of chooseColor will same as propsChooseColor.
<template>
...
data color: {{ chooseColor }} // RETURN BLACK
props color: {{ propsChooseColor }} // RETURN BLACK
...
</template>
I try to debug it and found that beforeUpdate hook is called if the props called in template.
What is happening? How do I initialize data without call the props? Approach usinh Computed property might not suited because i need to modify the data.
Edit. I also fetching data in the root component beforeRouteEnter hook like this.
beforeRouteEnter (to, from, next) {
const _id = to.query._id
const size = to.query.size
const color = to.query.color
axios.get(`http://localhost:8081/api/product-details/${_id}`)
.then(response => {
next(vm => {
vm.id = _id
vm.chooseSize = size
vm.chooseColor = color
vm.product = JSON.parse(JSON.stringify(response.data))
axios.get(`http://localhost:8081/api/product/all-seller/${vm.product.product_fullName}`)
.then(response => {
vm.productAllSeller = JSON.parse(JSON.stringify(response.data))
vm.fetchdataComplete = true
})
})
})
}