prop value is undefined on first but not on second render - reactjs

I'm running on react 18.2.0 nextjs1 0.1.0 node v18.12.1.
I've encountered a strange case where on the first render, a prop is undefined, but on the second render it has it. The variable is defined at the beginning of the parent:
default function Home() {
console.log('executing home');
.
.
let LocationsData = [];
console.log('defined LocationsData',LocationsData.length);
.
.
.
return (
<>
<BuildCountrieslist data={LocationsData} />
</>
)}
function BuildCountrieslist(props){
console.log('started BuildCountrieslist , Data.length is', props.data.length);
}
console.log shows:
executing home (as expected)
defined LocationsData 0 (as expected)
started BuildCountrieslist , **Data.length is undefined ( the error in question)**
executing home (as expected)
defined LocationsData 0 (as expected)
BuildCountrieslist , Data.length is 0 (as expected)

function App() {
console.log('executing home');
let LocationsData = [];
console.log('defined LocationsData', LocationsData.length);
return (
<>
<BuildCountrieslist data={LocationsData} />
</>
)
}
function BuildCountrieslist(props) {
console.log('started BuildCountrieslist , Data.length is', props.data.length);
}
export default App
It should be like this

Its my bad, ( hand on face )
Indeed I have some code after which LocationsData is set as undefined.
Sorry
:-(

Related

The useEffect won't change the state LIVE when clicked but content does change on reload

I'm trying to change my page's content when clicking on the link but the thing is it only changes on reload and not directly when clicked.
function Home( { category } ) {
const [news, setNews] = useState([]);
useEffect(() => {
async function newsArticles(){
const request = await axios.get(category);
console.log(request.data.articles);
setNews(request.data.articles);
return request;
}
newsArticles();
}, [category]);
return (
<div className='home'>
{news.map(ns => (
<NewsCard className='homeNewsCard' key = {ns.source.id} title = {ns.title} description = {ns.description} image = {ns.urlToImage} link = {ns.url}/>
))}
</div>
)
}
Since the effect captures the values at the time the component is rendered, any asynchronous code that executed in the effect will also see these values rather than the latest values. Example :
useEffect(()=>{
asyncFunc(props.val)
.then((res)=> setData(res + props.oth))
},[props.val]);
props.oth is used when the promise resolves, but the effecct captures the values of props.val and prips.oth at the time of render , the value of props.oth had changed during the time it took for the promise to reoslve , the code would see the old value
Solution :
you can either use reference to store the value of props.oth so your code will always see the latest value or you can add props.oth back to dependency array and return a cleanup function .
Example :
useEffect(()=>{
let cncl = false
asyncFunc(props.val)
.then((res)=>{
if(!cncl)
setData(res + props.oth)})
return ()=> cncl = true}
,[props.val, props.oth])
cncl flag is raised before running the effecct again (when props.val or props.oth have changes comapred with the previous render).

how to do error handling in react js functional components

{ props.history.map((element,index)=>{
return( <>
<Historyy temp={element.main.temp} imgvalue3={imgvalue3} imageUrl={element.weather[0].icon} mintemperature={element.main.temp_min} maxtemperature={element.main.temp_max} weather={element.weather[0].description} wind={element.wind.speed} humidity={element.main.humidity} time={index + 1}/>
</>
)
}) }
//this is the code i want to do that whenever my map function get a null value or undefined value i can simply show a other message like data not found.
a possible sollution, ternary operator. if history is null or undefined show your the h1 tag else show the history component.
{props.history ? props.history.map((element,index)=>{
return(<>
<Historyy temp={element.main.temp} imgvalue3={imgvalue3} imageUrl={element.weather[0].icon} mintemperature={element.main.temp_min} maxtemperature={element.main.temp_max} weather={element.weather[0].description} wind={element.wind.speed} humidity={element.main.humidity} time={index + 1}/>
</> ) }) : <h1>an error has occured</h1> }

"Object is possibly undefined" in React and TypeScript

certificate?: any;
<S.Contents>{certificate[0]}</S.Contents>
<S.Contents>{certificate[1]}</S.Contents>
<S.Contents>{certificate[3]}</S.Contents>
If the type of props is set to any and used as an index of an array, it works well. But if you change that any type to Array, Generic type'Array' requires 1 type argument(s). I get an error like this.
When I print typeof to the console, the object comes out, so when I change it from Array to object, I get an error other. "Object is possibly 'undefined'."
setCertificate(res.data.qualification.certificate);
Since it is an original array, I tried to create elements by turning it into map, but it also didn't work with a map is not a function error. I don't know what to do with me. Help.
You Always have to check for possible null or undefined values.
This is how I would do it to make it 100% safe
return (<div> {
certificate && certificate.length > 0 ? (
certificate.map((item, index) => (
<S.Contents key = {index}> {item}</S.Contents>
))
) : null
} </div>)
You get this error because you used an optional property for certificate. You need to add a check for undefined, to make sure it is actually defined.
Assuming your react function looks something like this, this would be a fast way to solve your issue:
function ReactComponent(props: {
certificate?: any[]
}) {
const certificate = props.certificate || [];
return (
{certificate.map((certificateItem) => (
<S.Contents>{certificateItem}</S.Contents>
))}
);
}
This line const certificate = props.certifate || []; assigns the first value if it is not undefined to the variable certificate otherwise the second. An if statement would also work but would be more verbose in this case:
function ReactComponent(props: {
certificate?: any[]
}) {
let certificate = props.certificate;
if(typeof certificate === "undefined") {
certificate = [];
}
return (
<div>
{certificate.map((certificateItem) => (
<S.Contents>{certificateItem}</S.Contents>
))}
</div>
);
}

React doesn't update value if inital setValue method of Hook is used

I created a minimalistic app using the npx create-react-app approach. I created a functional component and tried if an old setValue method of a useState hook updates the value maintained by the hook.
Therefore, I created an array listOfSetValueMethods that contains all setValue methods. In the myButtonClick() method I used the first setValue method to update the value of the hook: it does not work: react does not re-render anything: listOfSetValueMethods[0](scopeId+1);. If I use ANY other setValue method, it does work:
var myCounter=0;
var listOfSetValueMethods=[];
function MyComponent() {
const [currentScopeId,setValue]=useState(-1);
listOfSetValueMethods.push(setValue);
let scopeId=myCounter++;
console.log("scopeId: " + scopeId);
function myButtonClick(){
if(listOfSetValueMethods.length>0){
listOfSetValueMethods[0](scopeId+1); //does not work
//works: listOfSetValueMethods[1](scopeId+1);
console.log("setted value to:" + (scopeId+1) + ", current value in scope:" + currentScopeId);
}else{
setValue(scopeId);
}
}
return (
<div>
<b onClick={()=>{myButtonClick()}}> id: {currentScopeId}</b> <br />
</div>
);
}
What is the difference between calling listOfSetValueMethods[0](scopeId+1) and listOfSetValueMethods[X](scopeId+1) whereby X>0?
Output from console:
scopeId: 0
App.js:13 scopeId: 1
App.js:19 setted value to:2, current value in scope:-1
App.js:13 scopeId: 2
App.js:13 scopeId: 3
App.js:19 setted value to:2, current value in scope:-1
App.js:13 scopeId: 4
so the current scope id remains at -1!
App.js:13 scopeId: 5
I have no idea what you are trying to do and why you are making it so difficult. You keep pushing setValue to listOfSetValueMethods on every render but setValue never changes so there is no point.
You are logging a stale closure so maybe that's what you mean with "not working".
Here is your code working and showing that setValue is the same every render:
var myCounter = 0;
var listOfSetValueMethods = [];
function App() {
const [currentScopeId, setValue] = React.useState(-1);
listOfSetValueMethods.push(setValue);
let scopeId = myCounter++;
console.log('scopeId: ' + scopeId);
function myButtonClick() {
//this works just fine
listOfSetValueMethods[0](scopeId + 1);
console.log(
'setted value to:' +
(scopeId + 1) +
', current value in scope:' +
currentScopeId //this logs a stale closure
);
}
return (
<div>
are all items in listOfSetValueMethods the same:
{listOfSetValueMethods.every(
(item) => item === setValue
)+""}
<button onClick={() => {myButtonClick()}}>
id: {currentScopeId}
</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
So instead of having these myCounter and listOfSetValueMethods that would break if you render multiple instances of that component you could just do:
function myButtonClick() {
setValue(value=>value+1)
}

reactjs - valid React element (or null) must be returned

I have the following simple code :
var data = [{ email: "bob#gmail.com" },{ email: "toto#gmail.com" }];
var User = React.createClass({
render: function ()
{
return
(
<li>
{this.props.email}
</li>
);
}});
var UserList = React.createClass({
render: function ()
{
var userNodes = this.props.data.map(function (user)
{
console.log(user.email);
return
(
<User email={user.email} ></User>
);
});
return
(
<ul>{userNodes}</ul>
);
}});
ReactDOM.render(<UserList data={data} />, document.getElementById('root'));
and I got this error:
"A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object."
Here, the problem is in this line.
return
(
<li>
{this.props.email}
</li>
);
You have put the starting parentheses on the next line so when your code is converted into plain javascript code, it will look something like this.
render: function () {
return; // A semicolon has been inserted.
(React.createElement("li", null, this.props.email)); // unreachable code
}
You can see that a semicolon has been inserted by Javascript while interpreting your code, so no value is returned from the render function and you are getting this error.
To avoid this situation, you need to put the starting parentheses after the return statement, so that Javascript won't insert a semicolon until a matching ending parentheses is found. Like this,
return (
<li>
{this.props.email}
</li>
);
Now if you look at the generated code, it will look something like this
render: function () {
return (React.createElement("li", null, this.props.email));
}
Also, change
return
(
<ul>{userNodes}</ul>
);
to
return (
<ul>{userNodes}</ul>
);
Here, is the working fiddle. JSFiddle
I have also fixed the warning,
Each child in an array or iterator should have a unique "key" prop.
by passing key in your User component.

Resources