0

I have a parent component that inlude button.When i click on the button I can call the function inside the child component.here this is my parent component.I searched a little on how to do it.But i cant solve how to apply it on my code



function App() {


  const [bgColor,setBgColor]=useState("blue")
  const [isLoaded, setIsLoaded] = useState(false);
  const [text, setText] = useState([]);
  const [author, setAuthor] = useState([]);
  

  const getQuote = () => {
    const random = Math.floor(Math.random() * 1643 + 1);
    fetch('https://type.fit/api/quotes')
      .then((res) => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setText(result[random].text);
          setAuthor(result[random].author);
        },

     
      );
  };
  

  useEffect(() => {
    getQuote();
  }, []);


const redirect=()=>{

  window.location.href= 'https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text='+encodeURIComponent('"' + text + '" ' + author)
  ;

}
  return (
    <div
      className="d-flex flex-column  border border-primary w-50 shadow container"
      id="quote-box"
    >
      <h2 id="text" className="m-4">
        {text}
      </h2>
      <h4 id="author" className="text-info text-end m-3">
        {author}
      </h4>
      <button id="new-quote" className="btn btn-primary"onClick={getQuote} onClick={getQuote}>
        New Quote
      </button>

      <a onClick={redirect}
 id="tweet-quote" className="mt-5">
        <i className="fab fa-twitter fa-1x"></i>
      </a>

  <GeneralContext.Provider   value={{ value: [text, setText], value2: [author, setAuthor],value3:[bgColor,setBgColor] }}>
    <Theme />
    </GeneralContext.Provider>     
    </div>
  );
}

export default App;

this is my child component.And inside child component you can see handleClick function that I want to call by the button



export default function Theme() {


const {value,value2,value3}=useContext(GeneralContext)
const [text, setText] = value;
const [author,setAuthor] = value2;
const [bgColor,setBgColor]=value3

function random_bg_color() {
    var x = Math.floor(Math.random() * 120);
    var y = Math.floor(Math.random() * 120);
    var z = Math.floor(Math.random() * 120);
    const rgb = 'rgb(' + x + ',' + y + ',' + z + ')';
    return rgb;
  }

  const handleClick = ()=>{
    setBgColor(random_bg_color());
  }


    return (
        <div>
            <p>{bgColor}</p>
            <p>{author}</p>
        </div>
    )

}

sayinmehmet47
  • 490
  • 5
  • 21
  • Does this answer your question? [Call child method from parent](https://stackoverflow.com/questions/37949981/call-child-method-from-parent) – ibra Apr 16 '21 at 19:10
  • @ibra i read that before.I tried to apply it on my code.But I could not. I will use my button on parent for two reason.1)it will take random quote and random author, also 2)it will change background color of the box. I will take the background color from child element when clicking – sayinmehmet47 Apr 16 '21 at 19:12
  • Have you tried out my answer? I think it is what you are looking for – axtck Apr 16 '21 at 19:18

2 Answers2

0

Maybe you forgot to add useState to your code?
The best practice is to to update parent from child component. Pass bgColor, author and setBgColor to your <Theme /> component. Parent:

function App() {
    const { value, value2, value3 } = useContext(GeneralContext)
    const [text, setText] = value;
    const [author, setAuthor] = value2;
    const [bgColor, setBgColor] = value3
    return (
        <div
            className="d-flex flex-column  border border-primary w-50 shadow container" id="quote-box" >
            <h2 id="text" className="m-4">
                {text}
            </h2>
            <h4 id="author" className="text-info text-end m-3">
                {author}
            </h4>
            <button id="new-quote" className="btn btn-primary" onClick={ }>
                New Quote
        </button>
            <Theme bgColor={color => setBgColor(color)} author={author} bgColor={bgColor} />
        </div>
    );
}

Child:

export default function Theme({ bgColor, author, setBgColor }) {
    function random_bg_color() {
        var x = Math.floor(Math.random() * 120);
        var y = Math.floor(Math.random() * 120);
        var z = Math.floor(Math.random() * 120);
        const rgb = 'rgb(' + x + ',' + y + ',' + z + ')';
        return rgb;
    }

    const handleClick = () => {
        setBgColor(random_bg_color());
    }

    return (
        <div>
            <p>{bgColor}</p>
            <p>{author}</p>
            <button onClick={handleClick}>tikla</button>
        </div>
    )

}

In this way your component will be reusable, Just pass the props to it.

ibra
  • 390
  • 3
  • 13
  • but i want to use the button on parent to call child one – sayinmehmet47 Apr 16 '21 at 18:57
  • It's possible but not a good practice. you can use [refs](https://reactjs.org/docs/refs-and-the-dom.html), But in ref method you need also to pass the ref as a prop to child. The problem is answered [here](https://stackoverflow.com/questions/37949981/call-child-method-from-parent) – ibra Apr 16 '21 at 19:05
0

You can pass the function as props in the child component and handle it from the parent component.

Here is an example on how you could pass the function as prop in the child component:

export default function Child({ onLog }) {
  return (
    <div>
      <h1>Child</h1>
      <button onClick={() => onLog("log", "another")}>log</button>
    </div>
  );
}

Then, you can handle the function from the parent component:

export default function Parent() {
  const handleLogClick = (first, second) => {
    console.log(first);
    console.log(second);
  };

  return (
    <div>
      <Child onLog={handleLogClick} />
    </div>
  );
}
axtck
  • 3,707
  • 2
  • 10
  • 26