ReactJS Context: Passing array through context - reactjs

I currently have a project and I need to pass the array to another component for my search bar. I am using React's Context.
I've tried passing my data but I seem to get an undefined value in my console.
Code in Context.js
Export const SearchContext = createContext();
This is the code in MainPage.js:
const data = [json_1, json_2];
const array = data.map(values => {
const search = _.flattenDeep(values);
values.search = search;
return values;
})
<SearchContext.Provider value={array} />
and in my Searchbar.js
const options = useContext(SearchContext);
console.log(options);
<AutoComplete
className="searchbar"
placeholder="Search..."
dataSource = {options}
onfilterOption={(inputValue, option) =>
option.props.children.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
In the console.log I get an undefined value. This data should also be able to populate my search bar.

please look at this Gist : https://gist.github.com/nimahkh/9c008aaf2fd2d1cc83cd98c61e54979a
you have to wrap your component with Provider and inside of that component that is Wrapped , you have access to value , it's impossible to fetch value , out of the box

Related

I have a problem with react useState and rendering ! when i got a value passed by params to be setted in useState already declared with default value

when i got an value passed by params to be setted in useState already declared with default value first it render with the previous (default) value then render with new value that i'm passing in params .. is there is a possible way to render only after recieving the new value !? if i wasn't clear to describe my issue please don't hesitate to ask me for more details .. thanks in advance .
trying to set useState with new value expecting component render after recieving new value and not ernder with the default value.
here is my snippet code :-
const [searchParams] = useSearchParams();
const [selectedCollectionName] = searchParams.getAll(
"selectedCollectionName"
);
const [collectionName, setCollectionName] = useState(
"PersonalProfileAdminDashboard"
);
useEffect(() => {
setCollectionName(selectedCollectionName);
}, []);
it render firstly with PersonalProfileAdminDashboard and after that it render again with the new value comes from searchParams (selectedCollectionName) ..
i want to control render to be with value comes in searchParams !
and i tried :-
const [searchParams] = useSearchParams();
const [selectedCollectionName] = searchParams.getAll(
"selectedCollectionName"
);
const [collectionName, setCollectionName] = useState(
selectedCollectionName ? selectedCollectionName : "PersonalProfileAdminDashboard"
);
and i got the same issue.
If you could provide a snippet of your code that could help.
You could provide a child component with initial state like this:
const ParentComponent = () => {
const [initialValue, setInitialValue] = useState("Initial value")
return <ChildComponent key={initialValue} initialValue={initialValue} />
}
const ChildComponent = ({ initialValue }) => {
const [inputValue, setInputValue] = useState(initialValue)
return <input value={inputValue} onChange={handleChange} />
}
The key attribute on the child component will force react to create a new instance every time the initialValue changes. This should also render the component exclusively with the state you pass it.
This will work for small components, but if you are, for example, fetching data or handling complex logic in the child component, you should definitely handle the state within the child component.
You can also not render the component if the state is, for example, null by using a ternary operation in the return section:
// ...
return initialValue ? (
<input value={inputValue} onChange={handleChange} />
) : null
// ...
Please use the below render logic
class TestComponent extends React.Component
{
render(){
const {data}=this.props;
return(<Fragment>
{(data?<div>{data.id}</div>:null)}
</Fragment>);
}
}

Jest - how to get useSelect data in tesing file

I have a component in the React project which uses 2 useSelectors to get data for rendering the page. While testing I am able to cover the UI part but the conditional UI part is not coming on, as useSelector data is not replicatable via mock. Can someone help me.
const MyComponent = () => {
const { id } = useSelector(selecetdId);
const dataArray = useSelector(data);
return (
<div>
{!id ? (
<Fragment>
<AnotherCustomComponent />
{dataArray.length > 0 ? **<CustomTable dataArray={filteredSuppliers} />** : <NoData />}
</Fragment>
) : (
**<div className="supplier-details">
<CustomHeader />
</div>**
)}
</div>
);
};
As i dont have hold on the output from the useSelector id, dataArray, In testing i am not able to cover starred part of code
I have a feeling you are using ReactTestingLibrary and redux with dedux-toolkit ;)
You need to do two things:
Have a mocked state, with a values that can result in the condition you want to test
Render the component within redux provider
Quick sample
const renderComponent(props, reduxState) {
const reduxStore = configureStore({ reducer: {} /**/, preLoadedSate: reduxState });
return render(<Provider store={reduxStore}><MyComponentToBeTested ...props /></Provider>))
}
it("Should show something if id in the state is undefined", () => {
const stateSoThatUseSelectorWillReturnIdUndefined = { john: true };
const renderedResult = renderComponent({}, stateSoThatUseSelectorWillReturnIdUndefined);
/// expect something is rendered or not
});
More details here: redux state unit testing

Cannot map through array of files/images React

I am creating an image(s) upload component in React. Every time the file input field changes I am updating the images state. Below the input field I am trying to loop through the images and log their names in the console. However, as soon as I select an image, I get the error TypeError: images.map is not a function.
Here is my code:
import React, { useState } from 'react';
const ImagesInput = (props) => {
const [images, setImages] = useState([]);
const imageInputChange = (e) => {
setImages(e.target.files)
}
return (
<div>
<input {...props} type="file" onChange={imageInputChange} multiple />
{images.map((image) => {
console.log(image)
})}
</div>
)
}
export default ImagesInput;
The value of e.target.files is an array-like not an actual array. Just convert it to array before passing to setImages, like
setImages([...e.target.files])
Read here about array-like
Before
setImages(e.target.files)
Try to add a condition like this, make sure e.target.files is the image arr you want
if(e.target.files){
setImages(e.target.files)
}

Return value from react component

I am developing a react app, and I must to build a custmon dropdonw component, I need that my component returns the selected value.
I know the starndad way (or I think is the best way but, may be better if you know)
const getSelectedValue = (value) => {
console.log(value);
}
const component = <Dropdonw valueList={list} getSelectedValue={getSelectedValue} />
Is there any way to return de value using a variable or the javascript way component.options[e.selectedIndex].value. For example
const component = <Dropdonw valueList={list} />
...
<code>
...
console.log(component.getSelectedValue());
Could you tell me if there are others ways to get or return values, or the standard and best way y passing a function?
You can't return a single value from a react component. What you can do is lift the state up:
Parent:
const [dropdownVal, setDropdownVal] = useState(null)
<MyDropdown valueList={list} setDropdownVal={setDropdownVal} dropdownVal={dropdownVal} />
MyDropdown:
export const MyDropdown = ({valueList, dropdownVal, setDropdownVal}} => {
return(
<Dropdown valueList={valueList} value={dropdownVal} onChange={/* get value and call setDropdownVal */} />
)
}

Cant use values from (fetched) context(provider) as input to my useState

Short version:
I have a useEffect in a ContextProvider where I fetch some data from server. In my component I
use this Context and want to init another useState()-hook with the "incoming" data. The value in
[value, setValue] = useState(dataFromContext) does not get set/inited with dataFromContext. Why, oh why?
The very long version:
Im trying to follow (and expand on) this example of how to use context/useContext-hook in react
So, I have an AppContext and a ContextProvider, I wrap my in in index.js, everything in the example works nice.
Now I want to load data in useEffect inside my ContextProvider, so my context provider now looks like this
const AppContextProvider = ({ children }) => {
const profileInfoUrl = BASE_URL + `users/GetCurrentUsersProfileInfo/`
const {loading, getTokenSilently} = useAuth0();
const [profileInfo, setProfileInfo] = useState( {})
useEffect(() => {
if (!loading && profileInfo.user.username === '' ) {
Communication.get(profileInfoUrl, getTokenSilently, setProfileInfo);
}
},[loading, getTokenSilently])
const context = {
profileInfo,
setProfileInfo
};
return (
<AppContext.Provider value={ context }>
{children}
</AppContext.Provider>
);
}
Now, in my component, I want to display this data. One of them is users selected categories, a list of an id and isSelected, which should feed a checkboxlist.
const TsProfileSettingsPage = ( ) => {
//..
const { profileInfo, setProfileInfo } = useContext(AppContext);
const userCategories = Object.assign({}, ...profileInfo.userDetails.categories.map((c) => ({[c.id]: c})));
const [checkedCategories, setCheckedCategories] = useState(userCategories);
console.log("profileInfo.userDetails.categories : " + JSON.stringify(profileInfo.userDetails.categories));
console.log("userCategories : " + JSON.stringify(userCategories));//correct dictionary
console.log("checkedCategories : " + JSON.stringify(checkedCategories)); //empty object!
//...rest of code
So I load users selection and converts is to a dictionary that ends up in "userCategories". I use that "userCategories" to init checkedCategories. BUT, from the console.logs below, userCategories is set correctly, but checkedCategories is not, its becomes an empty object!
So my question is. Am I thinking wrong here? (obviously I am), I just want to have an external state.
Everything loads ok, but when I use it to init a useState() in my component it does not get set. I have tested to have another useEffect() in my component, but I just get the feeling that Im doing something more basic error.
Thanks for any help

Resources