how to set value in hooks - reactjs

I have a problem with hooks in ReactJS
as you see here i defined a prop that should call from child component
but when i want to change the value by calling change component it doesn't work and my state doesn't set.
can someone help me?
don't forget to read the comments
import React, {useState} from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
const setSelectedCollection = (e) => {
setCollection(e);
console.log(e); // returns the true value
console.log(collection); // returns null
}
return(
<div>
<Collection onChoosed={(e) => setSelectedCollection(e)}/>
</div>
)
}
export default SingleReminderPage;

Use setState with a callback function
const setSelectedCollection = (e) => {
setCollection((state)=> {...state, e});
}
setCollection(e) - wont update the state immediately.
I want to Understand SetState and Prevstate in ReactJS

This might help you around, the useEffect will be called on each colletion update
import React, { useState, useEffect } from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
useEffect(() => {
console.log(collection)
}, [collection])
return (
<div>
<Collection onChoosed={(e) => setCollection(e)} />
</div>
)
}
export default SingleReminderPage;

it seems like the setCollection is called after the logging action to check something like that you can print the collection value on the component itself
import React, {useState} from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
const setSelectedCollection = (e) => {
setCollection(e);
console.log(e); // returns the true value
console.log(collection); // returns null
}
return(
<div>
{collection}
<Collection onChoosed={(e) => setSelectedCollection(e)}/>
</div>
)
}
export default SingleReminderPage;

Related

Push state of reactive value to dependencies

I have an object: dynamicJSON that is changing. I would like to pass this object down to multiple dependencies: componentA, componentB. I also want the parts of the dependencies using the object to render when the object is changed.
I tried the useContext Hook, but received a dependency cycle error. What is the proper way to pass reactive values down to dependencies in react?
App.js
import { componetA } from "compA"
import { componetB } from "compB"
import { fetchLatestValue} from "api/fetchLatestValue"
import { useEffect } from "react"
export default function App() {
const dynamicJSON = ???;
useEffect(() => {
let timeoutId;
async function getlatestValue() {
try {
const data = await fetchLatestValue();
// update dynamicJSON here.
} catch (error) {
}
timeoutId = setTimeout(getlatestValue, 1000 * 1);
}
getlatestValue();
return () => {
clearTimeout(timeoutId);
};
}, []);
return (
<componetA />
<componetB />
);
}
compA
export default function componentA() {
const dynamicJSON = ???;
return(
<div>
{dynamicJSON.value}
</div>
)
};
Have you tried useEffect() with a dependency array? If anything in the dependency array is changed, the hook function will be triggered.
Reference: https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
Sorry I mis-read your question, you should pass dynamicJSON into both components as a prop. Make dynamicJSON a state is also a good idea.
Rule of thumb: if a prop or state of a component is changed, then this component is rerendered.
import { ComponentA } from "compA";
import { ComponentB } from "compB";
import { useEffect, useState } from "react";
export default function App() {
const [dynamicJSON, setDynamicJSON] = useState({});
//...omit
return (
<ComponentA dynamicJSON={dynamicJSON}/>
<ComponentB dynamicJSON={dynamicJSON}/>
);
}
CompA.js
export default function ComponentA(props) {
const { dynamicJSON } = props;
return(
<div>
{dynamicJSON.value}
</div>
)
};

SetState outside body reactjs

I try to set state , but I got error "Hooks can only be called inside of the body of a function component."
This is the code import React, { useState } from "react";
import AuthService from "../Services/AuthService";
const [Searchfile, setSearchfile] = useState([]);
AuthService.getalldata().then((res) => {
setSearchfile(res.data);
});
// const Searchfile = [
// { title: "ayam", singer: "gigi" },
// { title: "ucuk", singer: "asd" },
// ];
export default Searchfile;
Can someone explain to me why that is error and how to fix it ? :D
try adding a functional component and paste the code there.
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p> {count}</p>
<button onClick={() => setCount(count + 1)}>
click here
</button>
</div>
);
}
You are breaking the rules of hooks by attempting to call the useState hook outside of a functional component. After looking over your code, it seems like you want to create a custom hook of some sort so my suggestion would be todo something like this:
import { useState } from 'react'
import AuthService from "../Services/AuthService";
const UseSearchFile = () => {
const [Searchfile, setSearchfile] = useState([]);
AuthService.getalldata().then((res) => {
setSearchfile(res.data);
});
return {Searchfile}
}
export default UseSearchFile
you would then import it where you need it like so:
import UseSearchFile from ...correct path
and call it like so:
const { Searchfile } = UseSearchFile()

How to test code that uses a custom hook based on useContext with react-testing-library and jest

I've created a custom context hook - and I'm struggling to figure out how to pass values to its provider during testing.
My hook:
import React, { createContext, useContext, useState } from 'react';
const Context = createContext({});
export const ConfigurationProvider = ({ children }) => {
// Use State to keep the values
const [configuration, setConfiguration] = useState({});
// pass the value in provider and return
return (
<Context.Provider
value={{
configuration,
setConfiguration,
}}
>
{children}
</Context.Provider>
);
};
export const useConfigurationContext = () => useContext(Context);
export const { Consumer: ConfigurationConsumer } = Context;
This is how it's used in the application:
function App() {
return (
<ConfigurationProvider>
<div className="app">
<ComponentA />
</div>
</ConfigurationProvider>
);
}
And in ComponentA:
const ComponentA = () => {
// Get configuration
const configuration = useConfigurationContext();
return (
<div>{JSON.stringify(configuration)}</div>
)
}
This all works fine - considered that I'm calling setConfiguration from another component and set an object. Now for the testing part:
import React, { Component, createContext } from 'react';
import { render, waitFor } from '#testing-library/react';
import ComponentA from 'componentA';
const config = {
propertyA: 'hello',
};
test('renders the config', async () => {
const ConfigurationContext = createContext();
const { queryByText } = render(
<ConfigurationContext.Provider value={config}>
<ComponentA />
</ConfigurationContext.Provider>
);
expect(queryByText('hello')).toBeInTheDocument();
});
This doesn't work - I'm expecting the value that I'm sending in would be rendered in the div, but the context is an empty object. What am I doing wrong?
Thanks to Carle B. Navy I got the reason why it doesn't work. For other people two wonder what the solution is I fixed it by doing the following:
In my context hook, I changed the last line to export the provider as well:
export const { Consumer: ConfigConsumer, Provider: ConfigProvider } = Context;
Then in my test case, instead of creating a new context, I import the ConfigProvider at the top, and then:
const { queryByText } = render(
<ConfigProvider value={config}>
<ComponentA />
</ConfigProvider>
);
Thanks for helping me solve this and hope this helps someone else.

Passing String value through Props returned from useSelector Hook

I am working on ReactJS modal dialog and bind the values from redux slice through the useSelector hook. Currently I have two functions which are already dispatching using useDispatch hook and setting the props with 2 functions(onCancelHandler, submitHandler). Here I need to keep one more field which is string value(userName) and tried to keep that and usig the string value approvedUser in DeleteUserModalContent through the props. Initially I am able to get the value from props in DeleteUserModalContent
component but when submitHandler is executed the following error is occured.
Can't read property 'userName' which is undefined
Error at this line:
const approvedUser: string = selectedUser.userName;
Can any one tell me what is wrong here?
Thanks in Advance
Code Snippet:
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Modal } from '#material-ui/core';
import { AppState } from 'store/rootReducer';
import { hideModal } from 'store/common/modalSlice';
import { submitAction } from 'store/user-actions';
import { DeleteUserModalContent } from './DeleteUserModalContent';
export const DeleteUserModal: React.FC<{}> = () => {
const dispatch = useDispatch();
const selectedUser = useSelector((state: AppState) => {
const selectedUserId =
state.selectUserSlice.selectedUsers[0];
return state.userState[selectedUserId];
});
const onCancelHandler = () => {
dispatch(hideModal());
};
const submitHandler = () => {
dispatch(
submitAction(selectedUser.userName)
);
};
const approvedUser: string = selectedUser.userName;
console.log(selectedUser.userName);
const props = {
onResetHandler,
submitHandler,
approvedUser
};
return (
<Modal>
<>
<DeleteUserModalContent {...props} />
</>
</Modal>
);
};
When we use the returned value from the useSelector hook and use the same in other component DeleteUserModalContent by setting into props. Here we are able to use the approvedUser value initially but when submitHandler function is dispatched selectedUser.userName value becomes undefined, So we can put the condition check below:
const approvedUser: string = selectedUser?.userName
to avoid the above mentioned error.

Why is my search function not being passed?

I am trying to pass a search filter function into my search bar components. But i keep getting this error TypeError: Cannot read property 'search' of undefined
the search function is not recognized my context file is here
https://github.com/CodingOni/Ecommerce-Store/blob/master/src/context.js
import React, { useContext, useEffect, useRef } from 'react';
import ProductContext from '../../src/context';
const ProductFilter = () => {
const productConsumer = useContext(ProductContext);
const text = useRef('');
const { search, searchResults } = productConsumer;
useEffect(() => {
console.log(` product context ${productConsumer}`)
});
const onChange = e => {
if (text.current.value !== '') {
search(e.target.value);
} else {
}
};
return (
<form>
<input
ref={text}
type="text"
placeholder="Search Keywords..."
onChange={onChange}
id=""
/>
</form>
);
};
export default ProductFilter;
useContext accepts a context object (the value returned from
React.createContext) and returns the current context value for that
context.
You pass react component to useContext which is default export from '../../src/context'.
In context file you need export PoductContext
export { ProductProvider, ProductConsumer, ProductContext };
..
import {ProductContext} from '../../src/context';

Resources