REACT 3, Fetch() API, OpenAI API translation, useState() objects and conditional rendering, useContext() Providers and useCallback()
The fetch() API provides us a javascript interface to access the protocol, by using the global method fetch() and an URL path it returns a promise that will resolve into a response object.
The protocol is the set of rules used to define data formats, needed to allow data exchange between devices.
The promise-based fetch method can implement HTTP concepts like CORS (Cross-Origin Resource Sharing), an HTTP mechanic that allows a server to set the origin (domain, port, or scheme) from which the browser permits to load resources.
//We can add an init argument to the fetch(url, init) method
let init= {
method: 'POST', //GET, POST, PUT, DELETE, etc
body: JSON.stringify({
q: "Detectando el lenguaje" //body data type must match "Content-Type" header
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
}
We use try/catch to handle network and Cors errors, but we also need to check the promise.ok property to avoid other types of errors (like 404).
Request and Response bodies can only be used once, we use a request constructor to copy a fetch() request, and the copy must be done before the body is read
//The url detects the language the q string property is
let url = 'https://libretranslate.de/detect';
const lengua= new Request(url, init)
const lengua1 = new Request(url, init1);
try{
let response = await fetch( lengua );
if (!response.ok) {
throw new Error("Network response was not OK");
}
let commits = await response.json();
console.log( commits[0].language ) //ES
}catch(error){
console.log( {error.message} )
}
To configure the OpenAi translate API in ReactJs
import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
apiKey: "__Open_AI_key__",
});
const openai = new OpenAIApi(configuration);
We can prompt single or multiple language translations.
For a single-language translation, we modify the prompt.
//trim() removes the extra white spaces included in the translation
//it works for longer strings too
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: `Translate this into Spanish : cipolla`,
temperature: 0.3,
max_tokens: 100,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0.0,
});
console.log( response )
console.log( response.data.choices[0].text.trim() ); //cebolla
We use regex to create a useState() array of Node elements to render in the DOM.

We loop through the useState() node elements and, using regex, we modify useState() to render the translation using map().
const trova = new RegExp( "("+ word + ")", 'ig');
for(let x of canto){
if( trova.test( x.props.children[1] ) ){
tradotto = await traduce(toTranslate, Language)
setCanto((x)=> x.map( (str, index) =>
(index == id) ?
<div id={id} key={key} style={ {backgroundColor: "blue", color:"white"} }>
{tradotto}
</div>
:
str
))
}
}

Render useState() arrays and objects
The useState() is a react Hook we use to have state variables in function components
To modify useState() arrays we use the spread syntax and slice() method.
//slice() doesn't modify the starting useState() it creates a new one
const [linea, setLinea] = useState( [2, 3, 4, 5, 6, 7] )
function add(){
setLinea((x)=>( [11, ...x, 10] ) ) //[10, 2, 3, 4, 5, 6, 7, 10]
}
function remove(){
setLinea((x)=> (x.slice(1, x.length - 1)) ) //[2, 3, 4, 5, 6, 7]
}
The spread operator works for useState() objects too.


Conditional rendering using components props
The if statement is not a {javascript expression}, so we use the component's props in the function component to return and render JSX.
//We first use && logical operator to render the components onClick()
//do not use single numeric conditions, it will return {0} instead of false
const [press, setPress] = useState(false)
<div className="text-center">
<button className="btn btn-warning my-2" onClick={()=> setPress(true)}>
Open
</button>
</div>
{press &&
<div>
<Item name="valoriano" back="bg-warning" pack={press} />
<Item name="iride" back="bg-primary text-white" pack={press} />
<Item name="losco" back="bg-danger" pack={!press} />
</div>
}

//We then use the props in the function component
function Item({name, back, pack}){
return (
<li className={back}>
{name} {pack && "✔"}
</li>
)
}
function Item1({name, back, pack}){
let itemContent = name;
if (pack) {
itemContent = name + " ✔" ;
}
return (
<li className={back}>
{itemContent}
</li>
)
}
UseContext() and Provider components
To share data between separate and nested components we don't use props (prop-drilling), we useContext().
We set the Context provided values once.
import Relevant from './components/Externals';
const [drill, setDrill] = useState("element")
<OutContext.Provider value={{drill,setDrill}}>
<Relevant />
</OutContext.Provider>
In the imported component we deconstruct the context value object property.
function Relevant(){
const {drill, setDrill} = useContext(OutContext)
let dodice = drill + " added"
return(
<div>
Woglio vedere da extern l' {drill} and the {dodice}
<button className="btn btn-primary"
onClick={()=> setDrill("arco")}>
submit
</button>
<Sollievo />
</div>
)
}
And its nested components will have access to the same context value (even if imported).
function Sollievo(){
const {drill} = useContext(OutContext)
let dodice = drill + " 12"
return(
<div>
Abbiamo il tempo {dodice}
</div>
)
}
The createMethod API sets a global state context object that components can Provide and read. The useContext() React hook reads the component.provided context.
//The createContext() is the default value when no parent.provider value is available
const ThemeContext = createContext('red')
<ThemeContext.Provider value={"stripes"}>
<p>This is the {useContext(ThemeContext)} </p> //We have the value stripes
</ThemeContext.Provider>

We import createContext() to create multiple different Context providers.
import { useContext, createContext } from "react";
export const OutsideContext = createContext(15);
export const OutContext = createContext("Saul goodman");
import { OutContext, OutsideContext} from './components/Context';
We can override specific context values for specific children.
<ThemeContext.Provider value="dark">
<ThemeContext.Provider value="light">
<Footer />
</ThemeContext.Provider>
</ThemeContext.Provider>
Each time an exported Context.Provider component is used it will retain the value of its useContext() and can modify it.
const level = useContext(LevelContext);
<LevelContext.Provider value={level + 1}>
{children}
</LevelContext.Provider>

UseCallback() React hook with useMemo()
The context value object/props can pass functions(), and if any nested component changes then the passed function will be re-rendered, even if it returns the same value.
To optimize updating the component we useCallback() and useMemo().
const [currentUser, setCurrentUser] = useState(null);
function login(response) {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}
return (
<AuthContext.Provider value={{ currentUser, login }}>
<Page />
</AuthContext.Provider>
);
The useCallback() React Hook caches/saves a function and won't trigger it unless one of its dependencies array elements changes.
//All dependencies need to be present inside the function
useCallback(function, dependencies)
const handleSubmit = useCallback((orderDetails) => {
posting('/product/' + productId + '/buy', {
referrer,
orderDetails,
});
}, [productId, referrer]);
function posting(url, data) {
console.log('POST /' + url);
console.log(data);
}
Any function (){} or ()=>{} will be considered a new function, even if it includes the same values, and gets re-rendered, to avoid that we useMemo().
The useMemo() caches a function returned value while useCallback() keeps that function from re-rendering.
Rendering a component is different from triggering a function within it.
The onSubmit() will trigger the useCallback() function, and if the dependencies it uses don't change, the child component doesn't get re-rendered. The useState() counter gets rendered, so it re-renders the entire components on change.
We can update an useState() in a useCallback() function without including it in the dependencies.
//Instead of calling the useSatte() inside we pass an update function
const [todos, setTodos] = useState([]);
const handleAddTodo = useCallback((text) => {
const newTodo = { id: nextId++, text };
setTodos(todos => [...todos, newTodo]); //setTodos([...todos, newTodo]);
}, []); //[todos]
We useCallback() to optimize custom react hooks use.
//custom hooks are components that return javascript and not JSX
//they need to be called
import { useDispatch } from './dispatch.js';
const { dispatch } = useDispatch();
const navigate = useCallback((url) => {
dispatch({ type: 'navigate', url });
}, [dispatch]);
return {
navigate,
};
You can't call useCallback() in a loop, extract a component for the items, and useCallback() there
Last updated
Was this helpful?