Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

267
Vistas
Crear una cadena y convertirla a JSX

Tengo una situación en la que necesito analizar una cadena, romperla, volver a unirme y luego generar jsx a partir de ella. Tengo algo de éxito, pero también tengo que hacer que se pueda hacer clic para poder navegar al hacer clic, pero el problema es que onClick sigue siendo una cadena incluso después de la conversión.

Aquí están los detalles:

Obtengo una cadena en este formato:

Algo de texto @(nombre de usuario)[a_long_user_id_to_navigate_to] algo más de texto

Primero obtengo todas las menciones del texto y las convierto en objetos de nombres de usuario con sus ID.

y entonces:

 const createMessageWithActionableMentions = (message, mentions) => { mentions.map(mention => { message = message.replace('@'+'['+mention.username+']'+'('+mention.id+')',`<span style="color:${Colors.colorPrimary}; cursor: pointer" onClick={props.history.push('/some-route')}>@${mention.username}</span>`) }) return message }

el argumento del message en la función anterior contiene la cadena sin procesar y las mentions son una matriz de objetos de la siguiente manera:

 mentions = [ { username: 'abcd_1234', id: 'abcd_defg_hijk' }, { username: 'efgh_1234', id: 'wxyz_defg_jklm' } ...so on ]

Esto es lo que hago cuando agrego este texto para verlo:

<p dangerouslySetInnerHTML={{__html: message}}></p>

Esto es lo que veo en la página web:

Some text @username some more text

Esto es lo que veo en Inspector:

<span style="color:#03F29E; cursor: pointer" onclick="{props.history.push('/some-route')}">@username</span>

Ahora la pregunta es cómo manejo esta parte onclick="{props.history.push('/some-route')} para que funcione de la forma de reacción. Además, ¿lo estoy haciendo correctamente o hay una mejor manera?

about 4 years ago · Santiago Gelvez
3 Respuestas
Responde la pregunta

0

Podrías hacerlo así:

 const createMessageWithActionableMentions = (message, mentions) => { // Will return a list of JSX elements let output = [message]; // For every mention mentions.map( mention=>`@[${mention.username}](${mention.id})` ).forEach(mention => { // For every string we have output so far output = output.map( substring => { // Exclude existing JSX elements or strings that do not contain the mention if (typeof substring!=="string" || !substring.includes(mention)) return [substring] // We know the mention exists in this specific string segment so we need to find where it is so we can cut it out const index = substring.indexOf(mention) // Split the string into the part before, the part after, and the JSX element return [ substring.substring(0,index), <span style={{color:Colors.colorPrimary; cursor: "pointer"}} onClick={()=>props.history.push('/some-route')}>{mention.username}</span>, substring.substring(index+mention.length) ] } // Reduce the nested array of arrays back into a single array ).reduce((a,b)=>[...a,...b], []) }) return output }

No se necesitan travesuras html internas. Solo úsalo así:

 <p>{message}</p>
about 4 years ago · Santiago Gelvez Denunciar

0

Puede agregar controladores de clics a esos tramos usando Vanilla JS de la siguiente manera:

  1. Asigne una clase a esos intervalos, por ejemplo user-mention
 const createMessageWithActionableMentions = (message, mentions) => { mentions.map(mention => { message = message.replace('@'+'['+mention.username+']'+'('+mention.id+')',`<span style="color:${Colors.colorPrimary}; cursor: pointer" class="user-mention">@${mention.username}</span>`) }) return message }
  1. Agregue detectores de eventos a esos tramos. Si está utilizando componentes de función con ganchos, colóquelo dentro de un useEffect como este y asegúrese de que se llame a este gancho de efecto después de que los intervalos se agreguen al DOM.
 useEffect(() => { [...document.getElementsByClassName('user-mention')].forEach((element) => { element.addEventListener('click', () => { props.history.push('/some-route'); }) }) }, [/* Your dependencies */])

Tenga en cuenta que si los intervalos cambian (aumentan/disminuyen en número, por ejemplo), también debe manejar los detectores de eventos cuando cambien. Si esto se vuelve engorroso, puede usar la delegación de eventos

about 4 years ago · Santiago Gelvez Denunciar

0

Lo descubrí, esto se puede resolver usando la matriz, simplemente primero dividí el mensaje en una matriz de subcadenas:

 message = message.split(' ')

Luego lo asignó para encontrar menciones en esas subcadenas y reemplazó la substr respectiva con <span> :

 message.map( (substr, index) => { if(isMention(substr))){ found = mentions.find(mention => mention.username == substr.split('[').pop().split(']')[0]) if(found) { message[index] = <span style={{color:Colors.colorPrimary, cursor: "pointer"}}>{found.username}</span> } } })

el codigo final

 const createMessageWithActionableMentions = (message, mentions) => { let found = '' message = message.split(' ') message.map( (substr, index) => { if(isMention(substr))){ found = mentions.find(mention => mention.username == substr.split('[').pop().split(']')[0]) if(found) { message[index] = <span style={{color:Colors.colorPrimary, cursor: "pointer"}}>{found.username}</span> } } }) return message }

Luego lo representó como jsx

 <p>{message}</p>
about 4 years ago · Santiago Gelvez Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda