Javascript function passed as parameter not executing

51 Views Asked by At

I have an App.jsx, declaring a constant and setState routine. I put the setState in a function (update_word_list). I pass the function down to a sub-component. A console.log prints the typeof parameter as 'function' and a print of the function itself shows that the function is interpreted in the sub-component. The function does not execute.

I am new to Javascript. I apologise if I'm doing something dumb (needless to say...).

A lot of Code below, so I hope this describes localisation of issue in WordsSample.jsx. Overview/summary actions: App.jsx:

  1. Declare variable and setState: const [word_list, setWord_List] = useState(["1", "2"])
  2. Define function containing setState (note: console.log as first statement): function **Update_Word_List** (word_list) { console.log("Update word list inside app.js + word_list") setWord_List(word_list={word_list}) return (word_list) }
  3. Pass anonymised function to sub component: <WordSample word_list={word_list} dowords={()=>Update_Word_List}/>

WordsSample.jsx

  1. Pass props through to SendSample function onClick: <button type="submit" onClick={()=>SendSample(props)} name="genwords" id="genword">Names
  2. Receive props into SendSample, console.log typeof (recognised as function), and function (recognised as function invocation ??):
function SendSample( props ) {
    console.log("Props value: " + typeof(props.dowords))
    console.log("Props value: " + props.dowords)

  1. The problem!!! Try to execute the function: props.dowords(strwords).
  2. Localisation: console.log after the function should have executed: console.log("In theory we have done the function" + props.word_list) Notes:
  • The function should have changed the initial props.word_list value,which is unchanged.
  • The function invocation is after return from an axios.post. The axios.post has worked, and provided a 200 http return, and I have console.logged to ensure that data has been returned.

Console log:

Surrounding Code:

import './App.css';
import ControlS from './Controls'
import WordSample from './WordsSample'
import List_Words from './List_Words';
import {useState, useEffect} from 'react'


function App() {

  const [word_list, setWord_List] = useState(["1", "2"])

  function update_word_list (word_list)  {
    console.log("Update word list inside app.js  + word_list")
    setWord_List(word_list={word_list})
    return (word_list)
  }


  useEffect (() => {
    <App />
  }, []);
  

  
  return (
    <div className="App">
      <ControlS />
      <WordSample word_list={word_list} dowords={()=>update_word_list}/>
      <List_Words word_list={word_list}/>

Word_Sample sub component. Notes: Button in Word_sample invoking function sendSample with props.

import React, {useEffect, useState} from 'react';
import endPoints from './api';
import axios from 'axios';

export default function WordSample(props) {

    let [sample, setWordSample] =  useState("")

    useEffect(() => {
        loadSample()
    }, [])

const loadSample = async () => {
    const data = await endPoints.sample();
    setWordSample(sample=data)
}


function sendSample( props ) {
    console.log("Props value: " + props.dowords)

    let send = {}
    send['words'] =  sample

    axios.defaults.headers.post['Access-Control-Allow-Origin'] = "*";

    axios.post('/genwords', send, {
         headers: {
           'Content-Type': 'application/json',
         }
       }).then(res => {
            // console.log("Response words:" + JSON.stringify(res.data))
            let strwords = JSON.stringify(res.data)
            strwords = strwords.split(",")
            props.dowords(strwords)
            console.log("In theory we have done the function" + props.word_list)

            // word_list.forEach((word, i)=>console.log(word))
       }).catch(err=>console.log("Error found:  " + err))

       return(
        <>
        <h2>Literal</h2>

        </>
       )

    }
    

    return (
        <div className="wordsample">
            
                <div className="ctlheader">
                    <h1>Word Sample</h1>
                </div>
                <p>Type (or paste) the word sample that you would like to generate sci-fi names from</p>
            <form id="form" method="POST">
                <textarea placeholder={sample} id="word" name="words" required
                onChange={(e)=>setWordSample(sample=e.target.value)}></textarea>
                <br />
                <button type="submit" onClick={()=>sendSample(props)} name="genwords" id="genword">Names</button>
            </form>                  
        </div>
    )
}
1

There are 1 best solutions below

0
John Joyce On

Folks,

I've cracked this - not entirely to my satisfaction. Very simply, I pass the setState function directly:

I guess I'm confused about:

  1. Why so much documentation suggests this is a bad idea (which makes me uncomfortable that it still is!!!).
  2. Why this is different to passing any other function as a parameter...

So still some mystery. I'll update if I bottom it out. For now: with thanks for the kind help, I don't want anyone else spending time on this. Thanks https://stackoverflow.com/users/5053002/jaromanda-x in particular!!